From 8a228f22cd686063a64f8fb42a8944000cd04358 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 18 Nov 2019 12:00:36 +0100 Subject: [PATCH 0001/1381] DATAMONGO-2401 - Updated changelog. --- src/main/resources/changelog.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index c4c25e2918..03f861cddf 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,12 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.13.RELEASE (2019-11-18) +---------------------------------------------- +* DATAMONGO-2409 - Extension Function ReactiveFindOperation.DistinctWithProjection.asType() has wrong return type. +* DATAMONGO-2401 - Release 2.1.13 (Lovelace SR13). + + Changes in version 2.2.1.RELEASE (2019-11-04) --------------------------------------------- * DATAMONGO-2399 - Upgrade to mongo-java-driver 3.11.1. From 588ed2b0e22278f96d7d43c2b9eb00680875ca39 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 18 Nov 2019 12:31:44 +0100 Subject: [PATCH 0002/1381] DATAMONGO-2402 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 03f861cddf..021aafdd27 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.2.RELEASE (2019-11-18) +--------------------------------------------- +* DATAMONGO-2414 - ReactiveGridFsResource.getDownloadStream(…) hang if completion happens on event loop. +* DATAMONGO-2409 - Extension Function ReactiveFindOperation.DistinctWithProjection.asType() has wrong return type. +* DATAMONGO-2403 - ReactiveStringBasedAggregation / AggregationUtils fails on NPE because source or value is null. +* DATAMONGO-2402 - Release 2.2.2 (Moore SR2). + + Changes in version 2.1.13.RELEASE (2019-11-18) ---------------------------------------------- * DATAMONGO-2409 - Extension Function ReactiveFindOperation.DistinctWithProjection.asType() has wrong return type. From 7abf69e575b47cc5eb62276a588634de04f2c954 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 5 Nov 2019 10:46:29 +0100 Subject: [PATCH 0003/1381] DATAMONGO-2370 - Add support for $round aggregation operator. Original pull request: #803. --- .../core/aggregation/ArithmeticOperators.java | 117 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 1 + .../ArithmeticOperatorsUnitTests.java | 61 +++++++++ .../SpelExpressionTransformerUnitTests.java | 11 +- src/main/asciidoc/reference/mongodb.adoc | 2 +- 5 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 10785623e3..40f28d94ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -511,6 +511,27 @@ public StdDevSamp stdDevSamp() { : AccumulatorOperators.StdDevSamp.stdDevSampOf(expression); } + /** + * Creates new {@link AggregationExpression} that rounds a number to a whole integer or to a specified decimal + * place. + * + * @return new instance of {@link Round}. + * @since 3.0 + */ + public Round round() { + return usesFieldRef() ? Round.roundValueOf(fieldReference) : Round.roundValueOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that rounds a number to a specified decimal place. + * + * @return new instance of {@link Round}. + * @since 3.0 + */ + public Round roundToPlace(int place) { + return round().place(place); + } + private boolean usesFieldRef() { return fieldReference != null; } @@ -1422,4 +1443,100 @@ public static Trunc truncValueOf(Number value) { return new Trunc(value); } } + + /** + * {@link Round} rounds a number to a whole integer or to a specified decimal place.
+ *
    + *
  • If {@link Round#place(int)} resolves to a positive integer, {@code $round} rounds to the given decimal + * places.
  • + *
  • If {@link Round#place(int)} resolves to a negative integer, {@code $round} rounds to the left of the + * decimal.
  • + *
  • If {@link Round#place(int)} resolves to a zero, {@code $round} rounds using the first digit to the right of the + * decimal.
  • + *
+ * + * @since 3.0 + */ + public static class Round extends AbstractAggregationExpression { + + private Round(Object value) { + super(value); + } + + /** + * Round the value of the field that resolves to an integer, double, decimal, or long. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Round}. + */ + public static Round roundValueOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new Round(Collections.singletonList(Fields.field(fieldReference))); + } + + /** + * Round the outcome of the given expression hat resolves to an integer, double, decimal, or long. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Round}. + */ + public static Round roundValueOf(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + return new Round(Collections.singletonList(expression)); + } + + /** + * Round the given numeric (integer, double, decimal, or long) value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Round}. + */ + public static Round round(Number value) { + + Assert.notNull(value, "Value must not be null!"); + return new Round(Collections.singletonList(value)); + } + + /** + * The place to round to. Can be between -20 and 100, exclusive. + * + * @param place + * @return new instance of {@link Round}. + */ + public Round place(int place) { + return new Round(append(place)); + } + + /** + * The place to round to defined by an expression that resolves to an integer between -20 and 100, exclusive. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Round}. + */ + public Round placeOf(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + return new Round(append(expression)); + } + + /** + * The place to round to defined by via a field reference that resolves to an integer between -20 and 100, + * exclusive. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Round}. + */ + public Round placeOf(String fieldReference) { + + Assert.notNull(fieldReference, "fieldReference must not be null!"); + return new Round(append(Fields.field(fieldReference))); + } + + @Override + protected String getMongoMethod() { + return "$round"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index fd00c39a4f..dcc351fa0f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -84,6 +84,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("sqrt", singleArgRef().forOperator("$sqrt")); map.put("subtract", arrayArgRef().forOperator("$subtract")); map.put("trunc", singleArgRef().forOperator("$trunc")); + map.put("round", arrayArgRef().forOperator("$round")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java new file mode 100644 index 0000000000..4fd7a226a4 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2019 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.aggregation.ArithmeticOperators.*; + +import java.util.Arrays; +import java.util.Collections; + +import org.bson.Document; +import org.junit.jupiter.api.Test; + +/** + * @author Christoph Strobl + */ + +public class ArithmeticOperatorsUnitTests { + + @Test // DATAMONGO-2370 + void roundShouldWithoutPlace() { + + assertThat(valueOf("field").round().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(new Document("$round", Collections.singletonList("$field"))); + } + + @Test // DATAMONGO-2370 + void roundShouldWithPlace() { + + assertThat(valueOf("field").roundToPlace(3).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(new Document("$round", Arrays.asList("$field", Integer.valueOf(3)))); + } + + @Test // DATAMONGO-2370 + void roundShouldWithPlaceFromField() { + + assertThat(valueOf("field").round().placeOf("my-field").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(new Document("$round", Arrays.asList("$field", "$my-field"))); + } + + @Test // DATAMONGO-2370 + void roundShouldWithPlaceFromExpression() { + + assertThat(valueOf("field").round().placeOf((ctx -> new Document("$first", "$source"))) + .toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(new Document("$round", Arrays.asList("$field", new Document("$first", "$source")))); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index ac16820de3..28053b9508 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -23,7 +23,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; - import org.springframework.data.mongodb.core.Person; /** @@ -935,6 +934,16 @@ public void shouldRenderRange() { assertThat(transform("range(0, 10, 2)")).isEqualTo(Document.parse("{ \"$range\" : [0, 10, 2 ]}")); } + @Test // DATAMONGO-2370 + public void shouldRenderRound() { + assertThat(transform("round(field)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\"]}")); + } + + @Test // DATAMONGO-2370 + public void shouldRenderRoundWithPlace() { + assertThat(transform("round(field, 2)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\", 2]}")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 3eb5ec5112..f4a9a19852 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2516,7 +2516,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `sqrt`, `subtract` (*via `minus`), `trunc` +| `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `sqrt`, `subtract` (*via `minus`), `trunc`, `round` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` From 9f4872de4fea47e564842b6c741ceb5f66df317e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 5 Nov 2019 11:18:41 +0100 Subject: [PATCH 0004/1381] DATAMONGO-2370 - Polishing. Use JUnit Jupiter api for tests of touched classes and fix parsing errors in disabled ones. Original pull request: #803. --- .../SpelExpressionTransformerUnitTests.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 28053b9508..f0f1922525 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -20,9 +20,9 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.Person; /** @@ -38,8 +38,8 @@ public class SpelExpressionTransformerUnitTests { Data data; - @Before - public void setup() { + @BeforeEach + public void beforeEach() { this.data = new Data(); this.data.primitiveLongValue = 42; @@ -108,7 +108,7 @@ public void shouldRenderNestedFieldReference() { } @Test // DATAMONGO-774 - @Ignore + @Disabled public void shouldRenderNestedIndexedFieldReference() { // TODO add support for rendering nested indexed field references @@ -161,23 +161,25 @@ public void shouldRenderParameterExpressionResults() { } @Test // DATAMONGO-774 - @Ignore("TODO: mongo3 renders this a bit strange") public void shouldRenderNestedParameterExpressionResults() { assertThat( ((Document) transform("[0].primitiveLongValue + [0].primitiveDoubleValue + [0].doubleValue.longValue()", data)) - .toJson()).isEqualTo(Document.parse("{ \"$add\" : [ 42 , 1.2345 , 23]}").toJson()); + .toJson()) + .isEqualTo(Document + .parse("{ \"$add\" : [ { $numberLong : \"42\"} , 1.2345 , { $numberLong : \"23\" } ]}").toJson()); } @Test // DATAMONGO-774 - @Ignore("TODO: mongo3 renders this a bit strange") public void shouldRenderNestedParameterExpressionResultsInNestedExpressions() { assertThat( ((Document) transform("((1 + [0].primitiveLongValue) + [0].primitiveDoubleValue) * [0].doubleValue.longValue()", - data)).toJson()).isEqualTo( - new Document("$multiply", Arrays.asList(new Document("$add", Arrays.asList(1, 42L, 1.2345D, 23L)))) - .toJson()); + data)).toJson()) + .isEqualTo(new Document("$multiply", + Arrays. asList( + new Document("$add", Arrays. asList(1, new Document("$numberLong", "42"), 1.2345D)), + new Document("$numberLong", "23"))).toJson()); } @Test // DATAMONGO-840 @@ -680,9 +682,8 @@ public void shouldRenderMethodReferenceReverseArray() { } @Test // DATAMONGO-1548 - @Ignore("Document API cannot render String[]") public void shouldRenderMethodReferenceReduce() { - assertThat(transform("reduce(field, '', {'$concat':new String[]{'$$value','$$this'}})")).isEqualTo(Document.parse( + assertThat(transform("reduce(field, '', {'$concat':{'$$value','$$this'}})")).isEqualTo(Document.parse( "{ \"$reduce\" : { \"input\" : \"$field\" , \"initialValue\" : \"\" , \"in\" : { \"$concat\" : [ \"$$value\" , \"$$this\"]}}}")); } From cd4e4065ffba380c04e045561fdcc611f4fd4f98 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 20 Nov 2019 10:12:21 +0100 Subject: [PATCH 0005/1381] DATAMONGO-2370 - Polishing. Align since version to 2.3 until we have an indication for a major version bump. Tweak docs. Original pull request: #803. --- .../mongodb/core/aggregation/ArithmeticOperators.java | 8 ++++---- .../core/aggregation/ArithmeticOperatorsUnitTests.java | 5 +++-- src/main/asciidoc/reference/mongodb.adoc | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 40f28d94ce..fa21ccb955 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -516,7 +516,7 @@ public StdDevSamp stdDevSamp() { * place. * * @return new instance of {@link Round}. - * @since 3.0 + * @since 2.3 */ public Round round() { return usesFieldRef() ? Round.roundValueOf(fieldReference) : Round.roundValueOf(expression); @@ -526,7 +526,7 @@ public Round round() { * Creates new {@link AggregationExpression} that rounds a number to a specified decimal place. * * @return new instance of {@link Round}. - * @since 3.0 + * @since 2.3 */ public Round roundToPlace(int place) { return round().place(place); @@ -1445,7 +1445,7 @@ public static Trunc truncValueOf(Number value) { } /** - * {@link Round} rounds a number to a whole integer or to a specified decimal place.
+ * {@link Round} rounds a number to a whole integer or to a specified decimal place. *
    *
  • If {@link Round#place(int)} resolves to a positive integer, {@code $round} rounds to the given decimal * places.
  • @@ -1455,7 +1455,7 @@ public static Trunc truncValueOf(Number value) { * decimal. *
* - * @since 3.0 + * @since 2.3 */ public static class Round extends AbstractAggregationExpression { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 4fd7a226a4..8c11222a37 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -25,9 +25,10 @@ import org.junit.jupiter.api.Test; /** + * Unit tests for {@link Round}. + * * @author Christoph Strobl */ - public class ArithmeticOperatorsUnitTests { @Test // DATAMONGO-2370 @@ -41,7 +42,7 @@ void roundShouldWithoutPlace() { void roundShouldWithPlace() { assertThat(valueOf("field").roundToPlace(3).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(new Document("$round", Arrays.asList("$field", Integer.valueOf(3)))); + .isEqualTo(new Document("$round", Arrays.asList("$field", 3))); } @Test // DATAMONGO-2370 diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index f4a9a19852..fe5d0f8ffd 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2516,7 +2516,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `sqrt`, `subtract` (*via `minus`), `trunc`, `round` +| `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` From 1d98b77f3d9811d795d18a1db69b2ef135005bf8 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Sat, 9 Nov 2019 23:34:26 +0300 Subject: [PATCH 0006/1381] DATAMONGO-765 - Support skip and limit parameters in GridFsTemplate and ReactiveGridFsTemplate. Leverage `skip` and `limit` methods exposed in `GridFSFindIterable` to support limiting and skipping results. In particular these changes allow the `find(Query)` method to correctly consider parameters of a page request. Original pull request: #806. --- .../data/mongodb/gridfs/GridFsTemplate.java | 11 ++++++-- .../gridfs/ReactiveGridFsTemplate.java | 8 +++++- .../GridFsTemplateIntegrationTests.java | 21 +++++++++++++++ .../gridfs/ReactiveGridFsTemplateTests.java | 27 +++++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 98990d2d99..617e9164cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Optional; -import org.bson.BsonObjectId; import org.bson.Document; import org.bson.types.ObjectId; import org.springframework.core.io.support.ResourcePatternResolver; @@ -51,6 +50,7 @@ * @author Mark Paluch * @author Hartmut Lang * @author Niklas Helge Hanft + * @author Denis Zavedeev */ public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOperations, ResourcePatternResolver { @@ -166,7 +166,14 @@ public GridFSFindIterable find(Query query) { Document queryObject = getMappedQuery(query.getQueryObject()); Document sortObject = getMappedQuery(query.getSortObject()); - return getGridFs().find(queryObject).sort(sortObject); + GridFSFindIterable iterable = getGridFs().find(queryObject).sort(sortObject); + if (query.getSkip() > 0) { + iterable = iterable.skip(Math.toIntExact(query.getSkip())); + } + if (query.getLimit() > 0) { + iterable = iterable.limit(query.getLimit()); + } + return iterable; } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index cec6937630..dd7de6ce4a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -50,6 +50,7 @@ * * @author Mark Paluch * @author Nick Stolwijk + * @author Denis Zavedeev * @since 2.2 */ public class ReactiveGridFsTemplate extends GridFsOperationsSupport implements ReactiveGridFsOperations { @@ -261,7 +262,12 @@ protected GridFSFindPublisher prepareQuery(Query query) { Document sortObject = getMappedQuery(query.getSortObject()); GridFSFindPublisher publisherToUse = getGridFs().find(queryObject).sort(sortObject); - + if (query.getLimit() > 0) { + publisherToUse = publisherToUse.limit(query.getLimit()); + } + if (query.getSkip() > 0) { + publisherToUse = publisherToUse.skip(Math.toIntExact(query.getSkip())); + } Integer cursorBatchSize = query.getMeta().getCursorBatchSize(); if (cursorBatchSize != null) { publisherToUse = publisherToUse.batchSize(cursorBatchSize); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 4ddef14181..4d8c98c421 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -20,6 +20,7 @@ import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.gridfs.GridFsCriteria.*; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -27,6 +28,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import java.util.stream.Stream; import org.bson.BsonObjectId; import org.bson.Document; @@ -38,6 +40,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; @@ -61,6 +64,7 @@ * @author Martin Baumgartner * @author Hartmut Lang * @author Mark Paluch + * @author Denis Zavedeev */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:gridfs/gridfs.xml") @@ -289,6 +293,23 @@ public void getResourceShouldRetrieveContentByIdentity() throws IOException { } } + @Test // DATAMONGO-2411 + public void considersSkipLimitWhenQueryingFiles() { + Stream.of( // + "a", "aa", "aaa", // + "b", "bb", "bb", // + "c", "cc", "ccc", // + "d", "dd", "ddd") // + .forEach(filename -> operations.store(new ByteArrayInputStream(new byte[0]), filename)); + + PageRequest pageRequest = PageRequest.of(2, 3, Direction.ASC, "filename"); + List filenames = operations.find(new Query().with(pageRequest)) // + .map(GridFSFile::getFilename) // + .into(new ArrayList<>()); + + assertThat(filenames).containsExactly("c", "cc", "ccc"); + } + class Metadata { String version; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 9914443c8d..edaac16c54 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -21,6 +21,7 @@ import static org.springframework.data.mongodb.gridfs.GridFsCriteria.*; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.io.IOException; @@ -36,10 +37,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBuffer; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -48,6 +53,7 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.StreamUtils; +import com.mongodb.client.gridfs.model.GridFSFile; import com.mongodb.gridfs.GridFS; import com.mongodb.gridfs.GridFSInputFile; import com.mongodb.internal.HexUtils; @@ -60,6 +66,7 @@ * @author Mark Paluch * @author Christoph Strobl * @author Nick Stolwijk + * @author Denis Zavedeev */ @RunWith(SpringRunner.class) @ContextConfiguration("classpath:gridfs/reactive-gridfs.xml") @@ -282,6 +289,26 @@ public void getResourcesByPattern() throws IOException { .verifyComplete(); } + @Test // DATAMONGO-2411 + public void considersSkipLimitWhenQueryingFiles() { + DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); + DataBuffer buffer = bufferFactory.allocateBuffer(0); + Flux.just( // + "a", "aa", "aaa", // + "b", "bb", "bbb", // + "c", "cc", "ccc", // + "d", "dd", "ddd") // + .flatMap(fileName -> operations.store(Mono.just(buffer), fileName)) // + .blockLast(); + + PageRequest pageRequest = PageRequest.of(2, 3, Sort.Direction.ASC, "filename"); + operations.find(new Query().with(pageRequest)) // + .map(GridFSFile::getFilename) // + .as(StepVerifier::create) // + .expectNext("c", "cc", "ccc") // + .verifyComplete(); + } + static class Metadata { String version; } From dbf43941be81b030007e29b3a009841642ad1cad Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 26 Nov 2019 15:20:57 +0100 Subject: [PATCH 0007/1381] DATAMONGO-765 - Polishing. Reformat code. Update ticket references. Original pull request: #806. --- .../data/mongodb/gridfs/GridFsTemplate.java | 3 +++ .../data/mongodb/gridfs/ReactiveGridFsTemplate.java | 3 +++ .../mongodb/gridfs/GridFsTemplateIntegrationTests.java | 6 +++--- .../mongodb/gridfs/ReactiveGridFsTemplateTests.java | 10 ++++++---- src/main/asciidoc/new-features.adoc | 2 ++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 617e9164cb..74e398ee59 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -167,12 +167,15 @@ public GridFSFindIterable find(Query query) { Document sortObject = getMappedQuery(query.getSortObject()); GridFSFindIterable iterable = getGridFs().find(queryObject).sort(sortObject); + if (query.getSkip() > 0) { iterable = iterable.skip(Math.toIntExact(query.getSkip())); } + if (query.getLimit() > 0) { iterable = iterable.limit(query.getLimit()); } + return iterable; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index dd7de6ce4a..48e599ca43 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -262,12 +262,15 @@ protected GridFSFindPublisher prepareQuery(Query query) { Document sortObject = getMappedQuery(query.getSortObject()); GridFSFindPublisher publisherToUse = getGridFs().find(queryObject).sort(sortObject); + if (query.getLimit() > 0) { publisherToUse = publisherToUse.limit(query.getLimit()); } + if (query.getSkip() > 0) { publisherToUse = publisherToUse.skip(Math.toIntExact(query.getSkip())); } + Integer cursorBatchSize = query.getMeta().getCursorBatchSize(); if (cursorBatchSize != null) { publisherToUse = publisherToUse.batchSize(cursorBatchSize); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 4d8c98c421..33bb5dd734 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -293,10 +293,10 @@ public void getResourceShouldRetrieveContentByIdentity() throws IOException { } } - @Test // DATAMONGO-2411 + @Test // DATAMONGO-765 public void considersSkipLimitWhenQueryingFiles() { - Stream.of( // - "a", "aa", "aaa", // + + Stream.of("a", "aa", "aaa", // "b", "bb", "bb", // "c", "cc", "ccc", // "d", "dd", "ddd") // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index edaac16c54..065678928c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -289,17 +289,19 @@ public void getResourcesByPattern() throws IOException { .verifyComplete(); } - @Test // DATAMONGO-2411 + @Test // DATAMONGO-765 public void considersSkipLimitWhenQueryingFiles() { + DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); DataBuffer buffer = bufferFactory.allocateBuffer(0); - Flux.just( // - "a", "aa", "aaa", // + Flux.just("a", "aa", "aaa", // "b", "bb", "bbb", // "c", "cc", "ccc", // "d", "dd", "ddd") // .flatMap(fileName -> operations.store(Mono.just(buffer), fileName)) // - .blockLast(); + .as(StepVerifier::create) // + .expectNextCount(12) // + .verifyComplete(); PageRequest pageRequest = PageRequest.of(2, 3, Sort.Direction.ASC, "filename"); operations.find(new Query().with(pageRequest)) // diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 4ddf33ac3d..82142252ad 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,9 +5,11 @@ == What's New in Spring Data MongoDB 2.3 * Support for <>. +* Apply pagination when using GridFS `find(Query)`. [[new-features.2-2-0]] == What's New in Spring Data MongoDB 2.2 + * Compatibility with MongoDB 4.2 deprecating `eval`, `group` and `geoNear` Template API methods. * Extended SpEL aggregation support for MongoDB 3.4 and MongoDB 4.0 operators (see <>). * <> via `ReactiveQuerydslPredicateExecutor`. From c5b892f03bf63e32ed267390cb7ac6d6fe1ec840 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 3 Dec 2019 14:38:19 +0100 Subject: [PATCH 0008/1381] DATAMONGO-2410 - Fix Document to BasicDBObject conversion. Original pull request: #813. --- .../core/convert/MappingMongoConverter.java | 20 +++++++++++++------ .../MappingMongoConverterUnitTests.java | 8 ++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) 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 1721bd0d81..bc882d1a2f 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 @@ -239,12 +239,21 @@ private S read(TypeInformation type, @Nullable Bson bson, return conversionService.convert(bson, rawType); } - if (DBObject.class.isAssignableFrom(rawType)) { + if (Document.class.isAssignableFrom(rawType)) { return (S) bson; } - if (Document.class.isAssignableFrom(rawType)) { - return (S) bson; + if (DBObject.class.isAssignableFrom(rawType)) { + + if (bson instanceof DBObject) { + return (S) bson; + } + + if (bson instanceof Document) { + return (S) new BasicDBObject((Document) bson); + } + + return (S) DBObject.class.cast(bson); } if (typeToUse.isCollectionLike() && bson instanceof List) { @@ -273,9 +282,8 @@ private S read(TypeInformation type, @Nullable Bson bson, if (codecRegistryProvider != null) { Optional> codec = codecRegistryProvider.getCodecFor(rawType); - if(codec.isPresent()) { - return codec.get().decode(new JsonReader(target.toJson()), - DecoderContext.builder().build()); + if (codec.isPresent()) { + return codec.get().decode(new JsonReader(target.toJson()), DecoderContext.builder().build()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index b0567b77aa..da45e72e07 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -77,6 +77,7 @@ import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; import com.mongodb.DBRef; /** @@ -2067,6 +2068,13 @@ public void readsObjectIdAsDateWhenAnnotatedWithFieldTargetType() { assertThat(target.dateAsObjectId).isEqualTo(new Date(reference.getTimestamp())); } + @Test // DATAMONGO-2410 + public void shouldAllowReadingBackDbObject() { + + assertThat(converter.read(BasicDBObject.class, new org.bson.Document("property", "value"))) + .isEqualTo(new BasicDBObject("property", "value")); + } + static class GenericType { T content; } From 277b7a1c7c2457cabffd6edb87fef81e490018c3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 4 Dec 2019 08:56:20 +0100 Subject: [PATCH 0009/1381] DATAMONGO-2410 - Polishing. Simplify cast. Extend test with DBObject interface. Original pull request: #813. --- .../data/mongodb/core/convert/MappingMongoConverter.java | 2 +- .../mongodb/core/convert/MappingMongoConverterUnitTests.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) 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 bc882d1a2f..4c5b88ea01 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 @@ -253,7 +253,7 @@ private S read(TypeInformation type, @Nullable Bson bson, return (S) new BasicDBObject((Document) bson); } - return (S) DBObject.class.cast(bson); + return (S) bson; } if (typeToUse.isCollectionLike() && bson instanceof List) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index da45e72e07..1355507928 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.DocumentTestUtils.*; +import com.mongodb.DBObject; import lombok.EqualsAndHashCode; import lombok.RequiredArgsConstructor; @@ -2070,9 +2071,11 @@ public void readsObjectIdAsDateWhenAnnotatedWithFieldTargetType() { @Test // DATAMONGO-2410 public void shouldAllowReadingBackDbObject() { - + assertThat(converter.read(BasicDBObject.class, new org.bson.Document("property", "value"))) .isEqualTo(new BasicDBObject("property", "value")); + assertThat(converter.read(DBObject.class, new org.bson.Document("property", "value"))) + .isEqualTo(new BasicDBObject("property", "value")); } static class GenericType { From 60112b4d140f4a4b26b8cf1e8967e7cd49bb698a Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 19 Nov 2019 13:40:04 +0100 Subject: [PATCH 0010/1381] DATAMONGO-2418 - Obtain EvaluationContextExtensions lazily when parsing Bson queries. An eager evaluation of the context extension can lead to errors when e.g. the security context was not present. Original pull request: #814. --- .../repository/query/AggregationUtils.java | 2 +- .../repository/query/CollationUtils.java | 2 +- .../query/ReactiveStringBasedMongoQuery.java | 2 +- .../query/StringBasedMongoQuery.java | 2 +- .../util/json/ParameterBindingContext.java | 52 ++++++++++++++++--- .../json/ParameterBindingDocumentCodec.java | 2 +- .../util/json/ParameterBindingJsonReader.java | 10 ++++ .../ParameterBindingJsonReaderUnitTests.java | 23 ++++++++ 8 files changed, 83 insertions(+), 12 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index 7a3328b6fe..49cfee36c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -113,7 +113,7 @@ static List computePipeline(MongoQueryMethod method, Conve SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, - evaluationContextProvider.getEvaluationContext(method.getParameters(), accessor.getValues())); + () -> evaluationContextProvider.getEvaluationContext(method.getParameters(), accessor.getValues())); List target = new ArrayList<>(method.getAnnotatedAggregation().length); for (String source : method.getAnnotatedAggregation()) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index c8ceac681a..6547159b51 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -73,7 +73,7 @@ static Collation computeCollation(@Nullable String collationExpression, Converti if (StringUtils.trimLeadingWhitespace(collationExpression).startsWith("{")) { ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), - expressionParser, evaluationContextProvider.getEvaluationContext(parameters, accessor.getValues())); + expressionParser, () -> evaluationContextProvider.getEvaluationContext(parameters, accessor.getValues())); return Collation.from(CODEC.decode(collationExpression, bindingContext)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index 5e1e73040c..75c88961bb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -117,7 +117,7 @@ public ReactiveStringBasedMongoQuery(String query, ReactiveMongoQueryMethod meth protected Query createQuery(ConvertingParameterAccessor accessor) { ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, - evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); + () -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); Document queryObject = CODEC.decode(this.query, bindingContext); Document fieldsObject = CODEC.decode(this.fieldSpec, bindingContext); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index 7b045e8f98..34b54f826d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -116,7 +116,7 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati protected Query createQuery(ConvertingParameterAccessor accessor) { ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, - evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); + () -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); Document queryObject = CODEC.decode(this.query, bindingContext); Document fieldsObject = CODEC.decode(this.fieldSpec, bindingContext); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java index 012e67127a..a5133cefd8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java @@ -15,28 +15,54 @@ */ package org.springframework.data.mongodb.util.json; -import lombok.Getter; -import lombok.RequiredArgsConstructor; +import java.util.function.Supplier; +import org.springframework.data.util.Lazy; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; /** - * Reusable context for binding parameters to an placeholder or a SpEL expression within a JSON structure.
+ * Reusable context for binding parameters to a placeholder or a SpEL expression within a JSON structure.
* To be used along with {@link ParameterBindingDocumentCodec#decode(String, ParameterBindingContext)}. * * @author Christoph Strobl * @since 2.2 */ -@RequiredArgsConstructor -@Getter public class ParameterBindingContext { private final ValueProvider valueProvider; private final SpelExpressionParser expressionParser; - private final EvaluationContext evaluationContext; + private final Lazy evaluationContext; + + /** + * @param valueProvider + * @param expressionParser + * @param evaluationContext + * @deprecated since 2.2.3 - Please use + * {@link #ParameterBindingContext(ValueProvider, SpelExpressionParser, Supplier)} instead. + */ + @Deprecated + public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser expressionParser, + EvaluationContext evaluationContext) { + + this(valueProvider, expressionParser, () -> evaluationContext); + } + + /** + * @param valueProvider + * @param expressionParser + * @param evaluationContext a {@link Supplier} for {@link Lazy} context retrieval. + * @since 2.2.3 + */ + public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser expressionParser, + Supplier evaluationContext) { + + this.valueProvider = valueProvider; + this.expressionParser = expressionParser; + this.evaluationContext = evaluationContext instanceof Lazy ? (Lazy) evaluationContext : Lazy.of(evaluationContext); + } @Nullable public Object bindableValueForIndex(int index) { @@ -47,6 +73,18 @@ public Object bindableValueForIndex(int index) { public Object evaluateExpression(String expressionString) { Expression expression = expressionParser.parseExpression(expressionString); - return expression.getValue(this.evaluationContext, Object.class); + return expression.getValue(getEvaluationContext(), Object.class); + } + + public EvaluationContext getEvaluationContext() { + return this.evaluationContext.get(); + } + + public SpelExpressionParser getExpressionParser() { + return expressionParser; + } + + public ValueProvider getValueProvider() { + return valueProvider; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index 2ec51a79b8..a70b65bbff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -162,7 +162,7 @@ public void encode(final BsonWriter writer, final Document document, final Encod public Document decode(@Nullable String json, Object[] values) { return decode(json, new ParameterBindingContext((index) -> values[index], new SpelExpressionParser(), - EvaluationContextProvider.DEFAULT.getEvaluationContext(values))); + () -> EvaluationContextProvider.DEFAULT.getEvaluationContext(values))); } public Document decode(@Nullable String json, ParameterBindingContext bindingContext) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index 1063414f10..406c421393 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -26,6 +26,7 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -96,6 +97,15 @@ public ParameterBindingJsonReader(String json, Object[] values) { public ParameterBindingJsonReader(String json, ValueProvider accessor, SpelExpressionParser spelExpressionParser, EvaluationContext evaluationContext) { + this(json, accessor, spelExpressionParser, () -> evaluationContext); + } + + /** + * @since 2.2.3 + */ + public ParameterBindingJsonReader(String json, ValueProvider accessor, SpelExpressionParser spelExpressionParser, + Supplier evaluationContext) { + this.scanner = new JsonScanner(json); setContext(new Context(null, BsonContextType.TOP_LEVEL)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 66fd43fc8a..50d0390b21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -26,6 +26,10 @@ import org.bson.Document; import org.bson.codecs.DecoderContext; import org.junit.Test; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.TypedValue; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; /** * Unit tests for {@link ParameterBindingJsonReader}. @@ -197,6 +201,25 @@ public void bindNumberAsDate() { assertThat(target).isEqualTo(Document.parse("{ 'end_date' : { $gte : { $date : " + time + " } } } ")); } + @Test // DATAMONGO-2418 + public void shouldNotAccessSpElEveluationContextWhenNoSpelPresentInBindableTarget() { + + Object[] args = new Object[] { "value" }; + EvaluationContext evaluationContext = new StandardEvaluationContext() { + + @Override + public TypedValue getRootObject() { + throw new RuntimeException("o_O"); + } + }; + + ParameterBindingJsonReader reader = new ParameterBindingJsonReader("{ 'name':'?0' }", + new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext)); + Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build()); + + assertThat(target).isEqualTo(new Document("name", "value")); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); From 56fff286aabf1bc35d942385d353319997a5e2a5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 4 Dec 2019 10:30:44 +0100 Subject: [PATCH 0011/1381] DATAMONGO-2418 - Polishing. Reformat code. Original pull request: #814. --- .../data/mongodb/util/json/ParameterBindingContext.java | 2 +- .../data/mongodb/util/json/ParameterBindingJsonReader.java | 2 +- .../mongodb/util/json/ParameterBindingJsonReaderUnitTests.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java index a5133cefd8..0d919669d0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java @@ -77,7 +77,7 @@ public Object evaluateExpression(String expressionString) { } public EvaluationContext getEvaluationContext() { - return this.evaluationContext.get(); + return this.evaluationContext.get(); } public SpelExpressionParser getExpressionParser() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index 406c421393..ec334413d9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -101,7 +101,7 @@ public ParameterBindingJsonReader(String json, ValueProvider accessor, SpelExpre } /** - * @since 2.2.3 + * @since 2.2.3 */ public ParameterBindingJsonReader(String json, ValueProvider accessor, SpelExpressionParser spelExpressionParser, Supplier evaluationContext) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 50d0390b21..aa64c3ba78 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -202,7 +202,7 @@ public void bindNumberAsDate() { } @Test // DATAMONGO-2418 - public void shouldNotAccessSpElEveluationContextWhenNoSpelPresentInBindableTarget() { + public void shouldNotAccessSpElEvaluationContextWhenNoSpElPresentInBindableTarget() { Object[] args = new Object[] { "value" }; EvaluationContext evaluationContext = new StandardEvaluationContext() { From a1b5175299a3cd74a3486d33e69e4ea06e50b64c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 4 Dec 2019 11:43:07 +0100 Subject: [PATCH 0012/1381] DATAMONGO-2430 - Upgrade to mongo-java-driver 3.11.2. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4556c2de22..ff7167ef1d 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 3.11.1 + 3.11.2 1.12.0 1.19 From da7b51a51eb5d91d271f07bfc12f34b294d666d5 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 4 Dec 2019 11:40:47 +0100 Subject: [PATCH 0013/1381] DATAMONGO-2421 - Updated changelog. --- src/main/resources/changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 021aafdd27..65b68e7567 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,12 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.14.RELEASE (2019-12-04) +---------------------------------------------- +* DATAMONGO-2421 - Release 2.1.14 (Lovelace SR14). +* DATAMONGO-2410 - Using BasicDBObject as an entity caused java.lang.ClassCastException in runtime. + + Changes in version 2.2.2.RELEASE (2019-11-18) --------------------------------------------- * DATAMONGO-2414 - ReactiveGridFsResource.getDownloadStream(…) hang if completion happens on event loop. @@ -2814,3 +2820,4 @@ Repository * Namespace support for Mongo repositories * Allow usage of pagination and sorting with repositories + From 674f0cca2b55785ac641061f4e5427c971e73331 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 4 Dec 2019 14:11:36 +0100 Subject: [PATCH 0014/1381] DATAMONGO-2422 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 65b68e7567..901ab39775 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.3.RELEASE (2019-12-04) +--------------------------------------------- +* DATAMONGO-2430 - Upgrade to mongo-java-driver 3.11.2. +* DATAMONGO-2422 - Release 2.2.3 (Moore SR3). +* DATAMONGO-2418 - Application Context Doesn't start with @Query. +* DATAMONGO-2410 - Using BasicDBObject as an entity caused java.lang.ClassCastException in runtime. + + Changes in version 2.1.14.RELEASE (2019-12-04) ---------------------------------------------- * DATAMONGO-2421 - Release 2.1.14 (Lovelace SR14). @@ -2821,3 +2829,4 @@ Repository * Allow usage of pagination and sorting with repositories + From eacfe2b8f70ae5d4b70aa6c17612825278330400 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 7 Jan 2020 08:59:27 +0100 Subject: [PATCH 0015/1381] DATAMONGO-2444 - Update copyright years to 2020. --- .../springframework/data/mongodb/core/ProjectionsBenchmark.java | 2 +- .../data/mongodb/core/convert/DbRefMappingBenchmark.java | 2 +- .../mongodb/core/convert/MappingMongoConverterBenchmark.java | 2 +- .../data/mongodb/microbenchmark/AbstractMicrobenchmark.java | 2 +- .../data/mongodb/microbenchmark/HttpResultsWriter.java | 2 +- .../data/mongodb/microbenchmark/MongoResultsWriter.java | 2 +- .../data/mongodb/microbenchmark/ResultsWriter.java | 2 +- .../springframework/data/mongodb/BulkOperationException.java | 2 +- .../springframework/data/mongodb/ClientSessionException.java | 2 +- .../org/springframework/data/mongodb/CodecRegistryProvider.java | 2 +- .../data/mongodb/InvalidMongoDbApiUsageException.java | 2 +- .../org/springframework/data/mongodb/LazyLoadingException.java | 2 +- .../org/springframework/data/mongodb/MongoCollectionUtils.java | 2 +- .../org/springframework/data/mongodb/MongoDatabaseUtils.java | 2 +- .../java/org/springframework/data/mongodb/MongoDbFactory.java | 2 +- .../org/springframework/data/mongodb/MongoResourceHolder.java | 2 +- .../org/springframework/data/mongodb/MongoSessionProvider.java | 2 +- .../springframework/data/mongodb/MongoTransactionException.java | 2 +- .../springframework/data/mongodb/MongoTransactionManager.java | 2 +- .../data/mongodb/ReactiveMongoDatabaseFactory.java | 2 +- .../data/mongodb/ReactiveMongoDatabaseUtils.java | 2 +- .../data/mongodb/ReactiveMongoResourceHolder.java | 2 +- .../data/mongodb/ReactiveMongoTransactionManager.java | 2 +- .../data/mongodb/SessionAwareMethodInterceptor.java | 2 +- .../springframework/data/mongodb/SessionSynchronization.java | 2 +- .../data/mongodb/UncategorizedMongoDbException.java | 2 +- .../data/mongodb/config/AbstractMongoClientConfiguration.java | 2 +- .../data/mongodb/config/AbstractMongoConfiguration.java | 2 +- .../data/mongodb/config/AbstractReactiveMongoConfiguration.java | 2 +- .../java/org/springframework/data/mongodb/config/BeanNames.java | 2 +- .../data/mongodb/config/EnableMongoAuditing.java | 2 +- .../data/mongodb/config/GeoJsonConfiguration.java | 2 +- .../data/mongodb/config/GridFsTemplateParser.java | 2 +- .../data/mongodb/config/MappingMongoConverterParser.java | 2 +- .../data/mongodb/config/MongoAuditingBeanDefinitionParser.java | 2 +- .../data/mongodb/config/MongoAuditingRegistrar.java | 2 +- .../springframework/data/mongodb/config/MongoClientParser.java | 2 +- .../data/mongodb/config/MongoConfigurationSupport.java | 2 +- .../data/mongodb/config/MongoCredentialPropertyEditor.java | 2 +- .../data/mongodb/config/MongoDbFactoryParser.java | 2 +- .../org/springframework/data/mongodb/config/MongoJmxParser.java | 2 +- .../data/mongodb/config/MongoNamespaceHandler.java | 2 +- .../springframework/data/mongodb/config/MongoParsingUtils.java | 2 +- .../data/mongodb/config/MongoTemplateParser.java | 2 +- .../data/mongodb/config/ReadPreferencePropertyEditor.java | 2 +- .../data/mongodb/config/ServerAddressPropertyEditor.java | 2 +- .../data/mongodb/config/StringToWriteConcernConverter.java | 2 +- .../data/mongodb/config/WriteConcernPropertyEditor.java | 2 +- .../org/springframework/data/mongodb/core/AggregationUtil.java | 2 +- .../org/springframework/data/mongodb/core/BulkOperations.java | 2 +- .../springframework/data/mongodb/core/ChangeStreamEvent.java | 2 +- .../springframework/data/mongodb/core/ChangeStreamOptions.java | 2 +- .../springframework/data/mongodb/core/CollectionCallback.java | 2 +- .../springframework/data/mongodb/core/CollectionOptions.java | 2 +- .../java/org/springframework/data/mongodb/core/CountQuery.java | 2 +- .../org/springframework/data/mongodb/core/CursorPreparer.java | 2 +- .../java/org/springframework/data/mongodb/core/DbCallback.java | 2 +- .../data/mongodb/core/DefaultBulkOperations.java | 2 +- .../data/mongodb/core/DefaultIndexOperations.java | 2 +- .../data/mongodb/core/DefaultIndexOperationsProvider.java | 2 +- .../data/mongodb/core/DefaultReactiveIndexOperations.java | 2 +- .../data/mongodb/core/DefaultScriptOperations.java | 2 +- .../data/mongodb/core/DefaultWriteConcernResolver.java | 2 +- .../data/mongodb/core/DocumentCallbackHandler.java | 2 +- .../org/springframework/data/mongodb/core/EntityOperations.java | 2 +- .../data/mongodb/core/ExecutableAggregationOperation.java | 2 +- .../mongodb/core/ExecutableAggregationOperationSupport.java | 2 +- .../data/mongodb/core/ExecutableFindOperation.java | 2 +- .../data/mongodb/core/ExecutableFindOperationSupport.java | 2 +- .../data/mongodb/core/ExecutableInsertOperation.java | 2 +- .../data/mongodb/core/ExecutableInsertOperationSupport.java | 2 +- .../data/mongodb/core/ExecutableMapReduceOperation.java | 2 +- .../data/mongodb/core/ExecutableMapReduceOperationSupport.java | 2 +- .../data/mongodb/core/ExecutableRemoveOperation.java | 2 +- .../data/mongodb/core/ExecutableRemoveOperationSupport.java | 2 +- .../data/mongodb/core/ExecutableUpdateOperation.java | 2 +- .../data/mongodb/core/ExecutableUpdateOperationSupport.java | 2 +- .../springframework/data/mongodb/core/FindAndModifyOptions.java | 2 +- .../data/mongodb/core/FindAndReplaceOptions.java | 2 +- .../data/mongodb/core/FindPublisherPreparer.java | 2 +- .../data/mongodb/core/FluentMongoOperations.java | 2 +- .../springframework/data/mongodb/core/GeoCommandStatistics.java | 2 +- .../org/springframework/data/mongodb/core/IndexConverters.java | 2 +- .../org/springframework/data/mongodb/core/MappedDocument.java | 2 +- .../data/mongodb/core/MappingMongoJsonSchemaCreator.java | 2 +- .../java/org/springframework/data/mongodb/core/MongoAction.java | 2 +- .../springframework/data/mongodb/core/MongoActionOperation.java | 2 +- .../java/org/springframework/data/mongodb/core/MongoAdmin.java | 2 +- .../springframework/data/mongodb/core/MongoAdminOperations.java | 2 +- .../data/mongodb/core/MongoClientFactoryBean.java | 2 +- .../data/mongodb/core/MongoClientOptionsFactoryBean.java | 2 +- .../data/mongodb/core/MongoDataIntegrityViolationException.java | 2 +- .../data/mongodb/core/MongoDbFactorySupport.java | 2 +- .../data/mongodb/core/MongoEncryptionSettingsFactoryBean.java | 2 +- .../data/mongodb/core/MongoExceptionTranslator.java | 2 +- .../data/mongodb/core/MongoJsonSchemaCreator.java | 2 +- .../org/springframework/data/mongodb/core/MongoOperations.java | 2 +- .../org/springframework/data/mongodb/core/MongoTemplate.java | 2 +- .../springframework/data/mongodb/core/PropertyOperations.java | 2 +- .../data/mongodb/core/ReactiveAggregationOperation.java | 2 +- .../data/mongodb/core/ReactiveAggregationOperationSupport.java | 2 +- .../data/mongodb/core/ReactiveChangeStreamOperation.java | 2 +- .../data/mongodb/core/ReactiveChangeStreamOperationSupport.java | 2 +- .../data/mongodb/core/ReactiveCollectionCallback.java | 2 +- .../data/mongodb/core/ReactiveDatabaseCallback.java | 2 +- .../data/mongodb/core/ReactiveFindOperation.java | 2 +- .../data/mongodb/core/ReactiveFindOperationSupport.java | 2 +- .../data/mongodb/core/ReactiveFluentMongoOperations.java | 2 +- .../data/mongodb/core/ReactiveInsertOperation.java | 2 +- .../data/mongodb/core/ReactiveInsertOperationSupport.java | 2 +- .../data/mongodb/core/ReactiveMapReduceOperation.java | 2 +- .../data/mongodb/core/ReactiveMapReduceOperationSupport.java | 2 +- .../data/mongodb/core/ReactiveMongoClientFactoryBean.java | 2 +- .../mongodb/core/ReactiveMongoClientSettingsFactoryBean.java | 2 +- .../springframework/data/mongodb/core/ReactiveMongoContext.java | 2 +- .../data/mongodb/core/ReactiveMongoOperations.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplate.java | 2 +- .../data/mongodb/core/ReactiveRemoveOperation.java | 2 +- .../data/mongodb/core/ReactiveRemoveOperationSupport.java | 2 +- .../data/mongodb/core/ReactiveSessionCallback.java | 2 +- .../data/mongodb/core/ReactiveSessionScoped.java | 2 +- .../data/mongodb/core/ReactiveUpdateOperation.java | 2 +- .../data/mongodb/core/ReactiveUpdateOperationSupport.java | 2 +- .../springframework/data/mongodb/core/ReadPreferenceAware.java | 2 +- .../org/springframework/data/mongodb/core/ScriptOperations.java | 2 +- .../org/springframework/data/mongodb/core/SessionCallback.java | 2 +- .../org/springframework/data/mongodb/core/SessionScoped.java | 2 +- .../data/mongodb/core/SimpleMongoClientDbFactory.java | 2 +- .../springframework/data/mongodb/core/SimpleMongoDbFactory.java | 2 +- .../data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java | 2 +- .../springframework/data/mongodb/core/WriteConcernResolver.java | 2 +- .../springframework/data/mongodb/core/WriteResultChecking.java | 2 +- .../data/mongodb/core/aggregation/Aggregation.java | 2 +- .../data/mongodb/core/aggregation/AggregationExpression.java | 2 +- .../core/aggregation/AggregationExpressionTransformer.java | 2 +- .../core/aggregation/AggregationFunctionExpressions.java | 2 +- .../data/mongodb/core/aggregation/AggregationOperation.java | 2 +- .../mongodb/core/aggregation/AggregationOperationContext.java | 2 +- .../mongodb/core/aggregation/AggregationOperationRenderer.java | 2 +- .../data/mongodb/core/aggregation/AggregationOptions.java | 2 +- .../data/mongodb/core/aggregation/AggregationResults.java | 2 +- .../mongodb/core/aggregation/AggregationSpELExpression.java | 2 +- .../data/mongodb/core/aggregation/AggregationUpdate.java | 2 +- .../data/mongodb/core/aggregation/AggregationUtils.java | 2 +- .../data/mongodb/core/aggregation/ArrayOperators.java | 2 +- .../data/mongodb/core/aggregation/BucketAutoOperation.java | 2 +- .../data/mongodb/core/aggregation/BucketOperation.java | 2 +- .../data/mongodb/core/aggregation/BucketOperationSupport.java | 2 +- .../data/mongodb/core/aggregation/ComparisonOperators.java | 2 +- .../data/mongodb/core/aggregation/ConditionalOperators.java | 2 +- .../data/mongodb/core/aggregation/ConvertOperators.java | 2 +- .../data/mongodb/core/aggregation/CountOperation.java | 2 +- .../data/mongodb/core/aggregation/ExposedFields.java | 2 +- .../aggregation/ExposedFieldsAggregationOperationContext.java | 2 +- .../data/mongodb/core/aggregation/FacetOperation.java | 2 +- .../springframework/data/mongodb/core/aggregation/Field.java | 2 +- .../springframework/data/mongodb/core/aggregation/Fields.java | 2 +- .../core/aggregation/FieldsExposingAggregationOperation.java | 2 +- .../data/mongodb/core/aggregation/GeoNearOperation.java | 2 +- .../data/mongodb/core/aggregation/GraphLookupOperation.java | 2 +- .../data/mongodb/core/aggregation/GroupOperation.java | 2 +- .../InheritingExposedFieldsAggregationOperationContext.java | 2 +- .../data/mongodb/core/aggregation/LimitOperation.java | 2 +- .../data/mongodb/core/aggregation/LookupOperation.java | 2 +- .../data/mongodb/core/aggregation/MatchOperation.java | 2 +- .../data/mongodb/core/aggregation/ObjectOperators.java | 2 +- .../data/mongodb/core/aggregation/OutOperation.java | 2 +- .../PrefixingDelegatingAggregationOperationContext.java | 2 +- .../data/mongodb/core/aggregation/ProjectionOperation.java | 2 +- .../RelaxedTypeBasedAggregationOperationContext.java | 2 +- .../data/mongodb/core/aggregation/ReplaceRootOperation.java | 2 +- .../data/mongodb/core/aggregation/ReplaceWithOperation.java | 2 +- .../data/mongodb/core/aggregation/SampleOperation.java | 2 +- .../data/mongodb/core/aggregation/SetOperation.java | 2 +- .../data/mongodb/core/aggregation/SkipOperation.java | 2 +- .../data/mongodb/core/aggregation/SortByCountOperation.java | 2 +- .../data/mongodb/core/aggregation/SortOperation.java | 2 +- .../mongodb/core/aggregation/SpelExpressionTransformer.java | 2 +- .../data/mongodb/core/aggregation/StringOperators.java | 2 +- .../core/aggregation/TypeBasedAggregationOperationContext.java | 2 +- .../data/mongodb/core/aggregation/TypedAggregation.java | 2 +- .../data/mongodb/core/aggregation/UnsetOperation.java | 2 +- .../data/mongodb/core/aggregation/UnwindOperation.java | 2 +- .../data/mongodb/core/convert/AbstractMongoConverter.java | 2 +- .../data/mongodb/core/convert/CustomConversions.java | 2 +- .../data/mongodb/core/convert/DbRefProxyHandler.java | 2 +- .../data/mongodb/core/convert/DbRefResolver.java | 2 +- .../data/mongodb/core/convert/DbRefResolverCallback.java | 2 +- .../data/mongodb/core/convert/DefaultDbRefProxyHandler.java | 2 +- .../data/mongodb/core/convert/DefaultDbRefResolver.java | 2 +- .../data/mongodb/core/convert/DefaultDbRefResolverCallback.java | 2 +- .../data/mongodb/core/convert/DefaultMongoTypeMapper.java | 2 +- .../data/mongodb/core/convert/DocumentAccessor.java | 2 +- .../data/mongodb/core/convert/DocumentPropertyAccessor.java | 2 +- .../data/mongodb/core/convert/GeoConverters.java | 2 +- .../data/mongodb/core/convert/JsonSchemaMapper.java | 2 +- .../data/mongodb/core/convert/LazyLoadingProxy.java | 2 +- .../data/mongodb/core/convert/MappingMongoConverter.java | 2 +- .../data/mongodb/core/convert/MongoConverter.java | 2 +- .../data/mongodb/core/convert/MongoConverters.java | 2 +- .../data/mongodb/core/convert/MongoCustomConversions.java | 2 +- .../data/mongodb/core/convert/MongoExampleMapper.java | 2 +- .../data/mongodb/core/convert/MongoJsonSchemaMapper.java | 2 +- .../data/mongodb/core/convert/MongoTypeMapper.java | 2 +- .../springframework/data/mongodb/core/convert/MongoWriter.java | 2 +- .../data/mongodb/core/convert/NoOpDbRefResolver.java | 2 +- .../springframework/data/mongodb/core/convert/ObjectPath.java | 2 +- .../springframework/data/mongodb/core/convert/QueryMapper.java | 2 +- .../springframework/data/mongodb/core/convert/UpdateMapper.java | 2 +- .../data/mongodb/core/convert/ValueResolver.java | 2 +- .../java/org/springframework/data/mongodb/core/geo/GeoJson.java | 2 +- .../data/mongodb/core/geo/GeoJsonGeometryCollection.java | 2 +- .../data/mongodb/core/geo/GeoJsonLineString.java | 2 +- .../springframework/data/mongodb/core/geo/GeoJsonModule.java | 2 +- .../data/mongodb/core/geo/GeoJsonMultiLineString.java | 2 +- .../data/mongodb/core/geo/GeoJsonMultiPoint.java | 2 +- .../data/mongodb/core/geo/GeoJsonMultiPolygon.java | 2 +- .../org/springframework/data/mongodb/core/geo/GeoJsonPoint.java | 2 +- .../springframework/data/mongodb/core/geo/GeoJsonPolygon.java | 2 +- .../java/org/springframework/data/mongodb/core/geo/Sphere.java | 2 +- .../springframework/data/mongodb/core/index/CompoundIndex.java | 2 +- .../data/mongodb/core/index/CompoundIndexDefinition.java | 2 +- .../data/mongodb/core/index/CompoundIndexes.java | 2 +- .../springframework/data/mongodb/core/index/DurationStyle.java | 2 +- .../data/mongodb/core/index/GeoSpatialIndexType.java | 2 +- .../data/mongodb/core/index/GeoSpatialIndexed.java | 2 +- .../data/mongodb/core/index/GeospatialIndex.java | 2 +- .../springframework/data/mongodb/core/index/HashIndexed.java | 2 +- .../springframework/data/mongodb/core/index/HashedIndex.java | 2 +- .../java/org/springframework/data/mongodb/core/index/Index.java | 2 +- .../data/mongodb/core/index/IndexDefinition.java | 2 +- .../springframework/data/mongodb/core/index/IndexDirection.java | 2 +- .../org/springframework/data/mongodb/core/index/IndexField.java | 2 +- .../springframework/data/mongodb/core/index/IndexFilter.java | 2 +- .../org/springframework/data/mongodb/core/index/IndexInfo.java | 2 +- .../data/mongodb/core/index/IndexOperations.java | 2 +- .../data/mongodb/core/index/IndexOperationsAdapter.java | 2 +- .../data/mongodb/core/index/IndexOperationsProvider.java | 2 +- .../springframework/data/mongodb/core/index/IndexPredicate.java | 2 +- .../springframework/data/mongodb/core/index/IndexResolver.java | 2 +- .../org/springframework/data/mongodb/core/index/Indexed.java | 2 +- .../springframework/data/mongodb/core/index/JustOnceLogger.java | 2 +- .../data/mongodb/core/index/MongoMappingEventPublisher.java | 2 +- .../mongodb/core/index/MongoPersistentEntityIndexCreator.java | 2 +- .../mongodb/core/index/MongoPersistentEntityIndexResolver.java | 2 +- .../data/mongodb/core/index/ReactiveIndexOperations.java | 2 +- .../mongodb/core/index/ReactiveIndexOperationsProvider.java | 2 +- .../core/index/ReactiveMongoPersistentEntityIndexCreator.java | 2 +- .../data/mongodb/core/index/TextIndexDefinition.java | 2 +- .../springframework/data/mongodb/core/index/TextIndexed.java | 2 +- .../data/mongodb/core/mapping/BasicMongoPersistentEntity.java | 2 +- .../data/mongodb/core/mapping/BasicMongoPersistentProperty.java | 2 +- .../mongodb/core/mapping/CachingMongoPersistentProperty.java | 2 +- .../org/springframework/data/mongodb/core/mapping/DBRef.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Document.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Field.java | 2 +- .../springframework/data/mongodb/core/mapping/FieldType.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Language.java | 2 +- .../org/springframework/data/mongodb/core/mapping/MongoId.java | 2 +- .../data/mongodb/core/mapping/MongoMappingContext.java | 2 +- .../data/mongodb/core/mapping/MongoPersistentEntity.java | 2 +- .../data/mongodb/core/mapping/MongoPersistentProperty.java | 2 +- .../data/mongodb/core/mapping/MongoSimpleTypes.java | 2 +- .../springframework/data/mongodb/core/mapping/TextScore.java | 2 +- .../data/mongodb/core/mapping/event/AbstractDeleteEvent.java | 2 +- .../mongodb/core/mapping/event/AbstractMongoEventListener.java | 2 +- .../data/mongodb/core/mapping/event/AfterConvertEvent.java | 2 +- .../data/mongodb/core/mapping/event/AfterDeleteEvent.java | 2 +- .../data/mongodb/core/mapping/event/AfterLoadEvent.java | 2 +- .../data/mongodb/core/mapping/event/AfterSaveEvent.java | 2 +- .../data/mongodb/core/mapping/event/AuditingEntityCallback.java | 2 +- .../data/mongodb/core/mapping/event/AuditingEventListener.java | 2 +- .../data/mongodb/core/mapping/event/BeforeConvertCallback.java | 2 +- .../data/mongodb/core/mapping/event/BeforeConvertEvent.java | 2 +- .../data/mongodb/core/mapping/event/BeforeDeleteEvent.java | 2 +- .../data/mongodb/core/mapping/event/BeforeSaveCallback.java | 2 +- .../data/mongodb/core/mapping/event/BeforeSaveEvent.java | 2 +- .../data/mongodb/core/mapping/event/LoggingEventListener.java | 2 +- .../data/mongodb/core/mapping/event/MongoMappingEvent.java | 2 +- .../core/mapping/event/ReactiveAuditingEntityCallback.java | 2 +- .../core/mapping/event/ReactiveBeforeConvertCallback.java | 2 +- .../mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java | 2 +- .../core/mapping/event/ValidatingMongoEventListener.java | 2 +- .../springframework/data/mongodb/core/mapreduce/GroupBy.java | 2 +- .../data/mongodb/core/mapreduce/GroupByResults.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceCounts.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceOptions.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceResults.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceTiming.java | 2 +- .../springframework/data/mongodb/core/messaging/Cancelable.java | 2 +- .../data/mongodb/core/messaging/ChangeStreamRequest.java | 2 +- .../data/mongodb/core/messaging/ChangeStreamTask.java | 2 +- .../data/mongodb/core/messaging/CursorReadingTask.java | 2 +- .../mongodb/core/messaging/DefaultMessageListenerContainer.java | 2 +- .../mongodb/core/messaging/LazyMappingDelegatingMessage.java | 2 +- .../springframework/data/mongodb/core/messaging/Message.java | 2 +- .../data/mongodb/core/messaging/MessageListener.java | 2 +- .../data/mongodb/core/messaging/MessageListenerContainer.java | 2 +- .../data/mongodb/core/messaging/SimpleMessage.java | 2 +- .../data/mongodb/core/messaging/Subscription.java | 2 +- .../data/mongodb/core/messaging/SubscriptionRequest.java | 2 +- .../data/mongodb/core/messaging/TailableCursorRequest.java | 2 +- .../data/mongodb/core/messaging/TailableCursorTask.java | 2 +- .../org/springframework/data/mongodb/core/messaging/Task.java | 2 +- .../data/mongodb/core/messaging/TaskFactory.java | 2 +- .../org/springframework/data/mongodb/core/query/BasicQuery.java | 2 +- .../springframework/data/mongodb/core/query/BasicUpdate.java | 2 +- .../org/springframework/data/mongodb/core/query/Collation.java | 2 +- .../org/springframework/data/mongodb/core/query/Criteria.java | 2 +- .../data/mongodb/core/query/CriteriaDefinition.java | 2 +- .../java/org/springframework/data/mongodb/core/query/Field.java | 2 +- .../org/springframework/data/mongodb/core/query/GeoCommand.java | 2 +- .../java/org/springframework/data/mongodb/core/query/Meta.java | 2 +- .../data/mongodb/core/query/MetricConversion.java | 2 +- .../data/mongodb/core/query/MongoRegexCreator.java | 2 +- .../org/springframework/data/mongodb/core/query/NearQuery.java | 2 +- .../java/org/springframework/data/mongodb/core/query/Query.java | 2 +- .../data/mongodb/core/query/SerializationUtils.java | 2 +- .../java/org/springframework/data/mongodb/core/query/Term.java | 2 +- .../springframework/data/mongodb/core/query/TextCriteria.java | 2 +- .../org/springframework/data/mongodb/core/query/TextQuery.java | 2 +- .../data/mongodb/core/query/UntypedExampleMatcher.java | 2 +- .../org/springframework/data/mongodb/core/query/Update.java | 2 +- .../data/mongodb/core/query/UpdateDefinition.java | 2 +- .../data/mongodb/core/schema/DefaultMongoJsonSchema.java | 2 +- .../data/mongodb/core/schema/DocumentJsonSchema.java | 2 +- .../mongodb/core/schema/IdentifiableJsonSchemaProperty.java | 2 +- .../data/mongodb/core/schema/JsonSchemaObject.java | 2 +- .../data/mongodb/core/schema/JsonSchemaProperty.java | 2 +- .../data/mongodb/core/schema/MongoJsonSchema.java | 2 +- .../data/mongodb/core/schema/TypedJsonSchemaObject.java | 2 +- .../data/mongodb/core/schema/UntypedJsonSchemaObject.java | 2 +- .../data/mongodb/core/script/ExecutableMongoScript.java | 2 +- .../data/mongodb/core/script/NamedMongoScript.java | 2 +- .../springframework/data/mongodb/core/spel/ExpressionNode.java | 2 +- .../core/spel/ExpressionTransformationContextSupport.java | 2 +- .../data/mongodb/core/spel/ExpressionTransformer.java | 2 +- .../org/springframework/data/mongodb/core/spel/LiteralNode.java | 2 +- .../data/mongodb/core/spel/MethodReferenceNode.java | 2 +- .../springframework/data/mongodb/core/spel/OperatorNode.java | 2 +- .../data/mongodb/core/validation/CriteriaValidator.java | 2 +- .../data/mongodb/core/validation/DocumentValidator.java | 2 +- .../data/mongodb/core/validation/JsonSchemaValidator.java | 2 +- .../springframework/data/mongodb/core/validation/Validator.java | 2 +- .../java/org/springframework/data/mongodb/gridfs/AntPath.java | 2 +- .../data/mongodb/gridfs/AsyncInputStreamAdapter.java | 2 +- .../data/mongodb/gridfs/BinaryStreamAdapters.java | 2 +- .../data/mongodb/gridfs/DataBufferPublisherAdapter.java | 2 +- .../org/springframework/data/mongodb/gridfs/GridFsCriteria.java | 2 +- .../springframework/data/mongodb/gridfs/GridFsOperations.java | 2 +- .../data/mongodb/gridfs/GridFsOperationsSupport.java | 2 +- .../org/springframework/data/mongodb/gridfs/GridFsResource.java | 2 +- .../org/springframework/data/mongodb/gridfs/GridFsTemplate.java | 2 +- .../data/mongodb/gridfs/ReactiveGridFsOperations.java | 2 +- .../data/mongodb/gridfs/ReactiveGridFsResource.java | 2 +- .../data/mongodb/gridfs/ReactiveGridFsTemplate.java | 2 +- .../springframework/data/mongodb/monitor/AbstractMonitor.java | 2 +- .../org/springframework/data/mongodb/monitor/AssertMetrics.java | 2 +- .../data/mongodb/monitor/BackgroundFlushingMetrics.java | 2 +- .../data/mongodb/monitor/BtreeIndexCounters.java | 2 +- .../springframework/data/mongodb/monitor/ConnectionMetrics.java | 2 +- .../springframework/data/mongodb/monitor/GlobalLockMetrics.java | 2 +- .../org/springframework/data/mongodb/monitor/MemoryMetrics.java | 2 +- .../springframework/data/mongodb/monitor/OperationCounters.java | 2 +- .../org/springframework/data/mongodb/monitor/ServerInfo.java | 2 +- .../springframework/data/mongodb/repository/Aggregation.java | 2 +- .../org/springframework/data/mongodb/repository/CountQuery.java | 2 +- .../springframework/data/mongodb/repository/DeleteQuery.java | 2 +- .../springframework/data/mongodb/repository/ExistsQuery.java | 2 +- .../java/org/springframework/data/mongodb/repository/Meta.java | 2 +- .../data/mongodb/repository/MongoRepository.java | 2 +- .../java/org/springframework/data/mongodb/repository/Near.java | 2 +- .../java/org/springframework/data/mongodb/repository/Query.java | 2 +- .../data/mongodb/repository/ReactiveMongoRepository.java | 2 +- .../org/springframework/data/mongodb/repository/Tailable.java | 2 +- .../data/mongodb/repository/cdi/MongoRepositoryBean.java | 2 +- .../data/mongodb/repository/cdi/MongoRepositoryExtension.java | 2 +- .../data/mongodb/repository/config/EnableMongoRepositories.java | 2 +- .../repository/config/EnableReactiveMongoRepositories.java | 2 +- .../mongodb/repository/config/MongoRepositoriesRegistrar.java | 2 +- .../config/MongoRepositoryConfigNamespaceHandler.java | 2 +- .../config/MongoRepositoryConfigurationExtension.java | 2 +- .../repository/config/ReactiveMongoRepositoriesRegistrar.java | 2 +- .../config/ReactiveMongoRepositoryConfigurationExtension.java | 2 +- .../data/mongodb/repository/query/AbstractMongoQuery.java | 2 +- .../mongodb/repository/query/AbstractReactiveMongoQuery.java | 2 +- .../data/mongodb/repository/query/AggregationUtils.java | 2 +- .../data/mongodb/repository/query/BooleanUtil.java | 2 +- .../data/mongodb/repository/query/CollationUtils.java | 2 +- .../mongodb/repository/query/ConvertingParameterAccessor.java | 2 +- .../mongodb/repository/query/DtoInstantiatingConverter.java | 2 +- .../data/mongodb/repository/query/MongoEntityInformation.java | 2 +- .../data/mongodb/repository/query/MongoEntityMetadata.java | 2 +- .../data/mongodb/repository/query/MongoParameterAccessor.java | 2 +- .../data/mongodb/repository/query/MongoParameters.java | 2 +- .../repository/query/MongoParametersParameterAccessor.java | 2 +- .../data/mongodb/repository/query/MongoQueryCreator.java | 2 +- .../data/mongodb/repository/query/MongoQueryExecution.java | 2 +- .../data/mongodb/repository/query/MongoQueryMethod.java | 2 +- .../data/mongodb/repository/query/PartTreeMongoQuery.java | 2 +- .../data/mongodb/repository/query/QueryUtils.java | 2 +- .../repository/query/ReactiveMongoParameterAccessor.java | 2 +- .../mongodb/repository/query/ReactiveMongoQueryExecution.java | 2 +- .../data/mongodb/repository/query/ReactiveMongoQueryMethod.java | 2 +- .../mongodb/repository/query/ReactivePartTreeMongoQuery.java | 2 +- .../repository/query/ReactiveStringBasedAggregation.java | 2 +- .../mongodb/repository/query/ReactiveStringBasedMongoQuery.java | 2 +- .../mongodb/repository/query/SimpleMongoEntityMetadata.java | 2 +- .../data/mongodb/repository/query/StringBasedAggregation.java | 2 +- .../data/mongodb/repository/query/StringBasedMongoQuery.java | 2 +- .../repository/support/IndexEnsuringQueryCreationListener.java | 2 +- .../repository/support/MappingMongoEntityInformation.java | 2 +- .../mongodb/repository/support/MongoAnnotationProcessor.java | 2 +- .../repository/support/MongoEntityInformationSupport.java | 2 +- .../data/mongodb/repository/support/MongoRepositoryFactory.java | 2 +- .../mongodb/repository/support/MongoRepositoryFactoryBean.java | 2 +- .../mongodb/repository/support/MongodbDocumentSerializer.java | 2 +- .../repository/support/QuerydslAbstractMongodbQuery.java | 2 +- .../mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java | 2 +- .../repository/support/QuerydslFetchableMongodbQuery.java | 2 +- .../data/mongodb/repository/support/QuerydslJoinBuilder.java | 2 +- .../data/mongodb/repository/support/QuerydslMongoOps.java | 2 +- .../repository/support/QuerydslMongoPredicateExecutor.java | 2 +- .../mongodb/repository/support/QuerydslMongoRepository.java | 2 +- .../repository/support/QuerydslPredicateExecutorSupport.java | 2 +- .../mongodb/repository/support/QuerydslRepositorySupport.java | 2 +- .../repository/support/ReactiveMongoRepositoryFactory.java | 2 +- .../repository/support/ReactiveMongoRepositoryFactoryBean.java | 2 +- .../support/ReactiveQuerydslMongoPredicateExecutor.java | 2 +- .../repository/support/ReactiveSpringDataMongodbQuery.java | 2 +- .../data/mongodb/repository/support/SimpleMongoRepository.java | 2 +- .../repository/support/SimpleReactiveMongoRepository.java | 2 +- .../data/mongodb/repository/support/SpringDataMongodbQuery.java | 2 +- .../mongodb/repository/support/SpringDataMongodbSerializer.java | 2 +- .../java/org/springframework/data/mongodb/util/BsonUtils.java | 2 +- .../org/springframework/data/mongodb/util/DBObjectUtils.java | 2 +- .../springframework/data/mongodb/util/MongoClientVersion.java | 2 +- .../springframework/data/mongodb/util/MongoDbErrorCodes.java | 2 +- .../data/mongodb/util/json/DateTimeFormatter.java | 2 +- .../org/springframework/data/mongodb/util/json/JsonBuffer.java | 2 +- .../org/springframework/data/mongodb/util/json/JsonScanner.java | 2 +- .../org/springframework/data/mongodb/util/json/JsonToken.java | 2 +- .../springframework/data/mongodb/util/json/JsonTokenType.java | 2 +- .../data/mongodb/util/json/ParameterBindingContext.java | 2 +- .../data/mongodb/util/json/ParameterBindingDocumentCodec.java | 2 +- .../data/mongodb/util/json/ParameterBindingJsonReader.java | 2 +- .../springframework/data/mongodb/util/json/ValueProvider.java | 2 +- .../src/test/java/ConfigClassInDefaultPackage.java | 2 +- .../src/test/java/ConfigClassInDefaultPackageUnitTests.java | 2 +- spring-data-mongodb/src/test/java/example/first/First.java | 2 +- spring-data-mongodb/src/test/java/example/second/Second.java | 2 +- .../java/org/springframework/data/mongodb/DependencyTests.java | 2 +- .../data/mongodb/MongoDatabaseUtilsUnitTests.java | 2 +- .../data/mongodb/MongoTransactionManagerUnitTests.java | 2 +- .../data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java | 2 +- .../data/mongodb/ReactiveMongoTransactionManagerUnitTests.java | 2 +- .../data/mongodb/ReactiveTransactionIntegrationTests.java | 2 +- .../data/mongodb/SessionAwareMethodInterceptorUnitTests.java | 2 +- .../data/mongodb/config/AbstractIntegrationTests.java | 2 +- .../mongodb/config/AbstractMongoConfigurationUnitTests.java | 2 +- .../AbstractReactiveMongoConfigurationIntegrationTests.java | 2 +- .../config/AbstractReactiveMongoConfigurationUnitTests.java | 2 +- .../data/mongodb/config/AuditingIntegrationTests.java | 2 +- .../mongodb/config/AuditingViaJavaConfigRepositoriesTests.java | 2 +- .../data/mongodb/config/CustomMongoTypeMapper.java | 2 +- .../mongodb/config/GeoJsonConfigurationIntegrationTests.java | 2 +- .../config/MappingMongoConverterParserIntegrationTests.java | 2 +- .../MappingMongoConverterParserValidationIntegrationTests.java | 2 +- .../data/mongodb/config/MongoAuditingRegistrarUnitTests.java | 2 +- .../data/mongodb/config/MongoClientParserIntegrationTests.java | 2 +- .../mongodb/config/MongoCredentialPropertyEditorUnitTests.java | 2 +- .../mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java | 2 +- .../mongodb/config/MongoDbFactoryParserIntegrationTests.java | 2 +- .../data/mongodb/config/MongoNamespaceReplicaSetTests.java | 2 +- .../data/mongodb/config/MongoNamespaceTests.java | 2 +- .../data/mongodb/config/MongoParserIntegrationTests.java | 2 +- .../data/mongodb/config/ReactiveAuditingTests.java | 2 +- .../mongodb/config/ReadPreferencePropertyEditorUnitTests.java | 2 +- .../mongodb/config/ServerAddressPropertyEditorUnitTests.java | 2 +- .../mongodb/config/StringToWriteConcernConverterUnitTests.java | 2 +- .../mongodb/config/WriteConcernPropertyEditorUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/AuditablePerson.java | 2 +- .../data/mongodb/core/ChangeStreamOptionsUnitTests.java | 2 +- .../springframework/data/mongodb/core/ClientSessionTests.java | 2 +- .../mongodb/core/CloseableIterableCursorAdapterUnitTests.java | 2 +- .../springframework/data/mongodb/core/CollationUnitTests.java | 2 +- .../springframework/data/mongodb/core/CountQueryUnitTests.java | 2 +- .../mongodb/core/DefaultBulkOperationsIntegrationTests.java | 2 +- .../data/mongodb/core/DefaultBulkOperationsUnitTests.java | 2 +- .../mongodb/core/DefaultIndexOperationsIntegrationTests.java | 2 +- .../data/mongodb/core/DefaultIndexOperationsUnitTests.java | 2 +- .../data/mongodb/core/DefaultReactiveIndexOperationsTests.java | 2 +- .../mongodb/core/DefaultReactiveIndexOperationsUnitTests.java | 2 +- .../data/mongodb/core/DefaultScriptOperationsTests.java | 2 +- .../data/mongodb/core/DefaultScriptOperationsUnitTests.java | 2 +- .../springframework/data/mongodb/core/DocumentTestUtils.java | 2 +- .../data/mongodb/core/EntityOperationUnitTests.java | 2 +- .../core/ExecutableAggregationOperationSupportUnitTests.java | 2 +- .../data/mongodb/core/ExecutableFindOperationSupportTests.java | 2 +- .../mongodb/core/ExecutableInsertOperationSupportUnitTests.java | 2 +- .../core/ExecutableMapReduceOperationSupportUnitTests.java | 2 +- .../mongodb/core/ExecutableRemoveOperationSupportTests.java | 2 +- .../mongodb/core/ExecutableUpdateOperationSupportTests.java | 2 +- .../test/java/org/springframework/data/mongodb/core/Friend.java | 2 +- .../data/mongodb/core/GeoCommandStatisticsUnitTests.java | 2 +- .../java/org/springframework/data/mongodb/core/JmxServer.java | 2 +- .../springframework/data/mongodb/core/JsonSchemaQueryTests.java | 2 +- .../mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java | 2 +- .../data/mongodb/core/MongoAdminIntegrationTests.java | 2 +- .../core/MongoClientOptionsFactoryBeanIntegrationTests.java | 2 +- .../mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java | 2 +- .../data/mongodb/core/MongoExceptionTranslatorUnitTests.java | 2 +- .../data/mongodb/core/MongoOperationsUnitTests.java | 2 +- .../data/mongodb/core/MongoTemplateCollationTests.java | 2 +- .../data/mongodb/core/MongoTemplateDbRefTests.java | 2 +- .../data/mongodb/core/MongoTemplateMappingTests.java | 2 +- .../springframework/data/mongodb/core/MongoTemplateTests.java | 2 +- .../data/mongodb/core/MongoTemplateTransactionTests.java | 2 +- .../data/mongodb/core/MongoTemplateUnitTests.java | 2 +- .../data/mongodb/core/MongoTemplateUpdateTests.java | 2 +- .../data/mongodb/core/MongoTemplateValidationTests.java | 2 +- .../springframework/data/mongodb/core/NoExplicitIdTests.java | 2 +- .../test/java/org/springframework/data/mongodb/core/Person.java | 2 +- .../org/springframework/data/mongodb/core/PersonExample.java | 2 +- .../data/mongodb/core/PersonExampleAppConfig.java | 2 +- .../org/springframework/data/mongodb/core/PersonWithAList.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfPrimitiveInt.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfPrimitiveLong.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfTypeBigInteger.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfTypeInteger.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfTypeLong.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfTypeObjectId.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfTypeString.java | 2 +- .../data/mongodb/core/PersonWithIdPropertyOfTypeUUID.java | 2 +- .../mongodb/core/PersonWithVersionPropertyOfTypeInteger.java | 2 +- .../data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java | 2 +- .../data/mongodb/core/PersonWith_idPropertyOfTypeObjectId.java | 2 +- .../data/mongodb/core/PersonWith_idPropertyOfTypeString.java | 2 +- .../springframework/data/mongodb/core/PersonWriteConverter.java | 2 +- .../java/org/springframework/data/mongodb/core/Portfolio.java | 2 +- .../springframework/data/mongodb/core/QueryByExampleTests.java | 2 +- .../data/mongodb/core/QueryCursorPreparerUnitTests.java | 2 +- .../core/ReactiveAggregationOperationSupportUnitTests.java | 2 +- .../mongodb/core/ReactiveChangeStreamOperationSupportTests.java | 2 +- .../core/ReactiveChangeStreamOperationSupportUnitTests.java | 2 +- .../data/mongodb/core/ReactiveClientSessionTests.java | 2 +- .../data/mongodb/core/ReactiveFindOperationSupportTests.java | 2 +- .../mongodb/core/ReactiveInsertOperationSupportUnitTests.java | 2 +- .../core/ReactiveMapReduceOperationSupportUnitTests.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplateCollationTests.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplateExecuteTests.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplateIndexTests.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplateTests.java | 2 +- .../mongodb/core/ReactiveMongoTemplateTransactionTests.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplateUnitTests.java | 2 +- .../data/mongodb/core/ReactiveMongoTemplateUpdateTests.java | 2 +- .../data/mongodb/core/ReactiveRemoveOperationSupportTests.java | 2 +- .../core/ReactiveSessionBoundMongoTemplateUnitTests.java | 2 +- .../data/mongodb/core/ReactiveUpdateOperationSupportTests.java | 2 +- .../data/mongodb/core/SerializationUtilsUnitTests.java | 2 +- .../data/mongodb/core/SessionBoundMongoTemplateTests.java | 2 +- .../data/mongodb/core/SessionBoundMongoTemplateUnitTests.java | 2 +- .../data/mongodb/core/SimpleMongoDbFactoryUnitTests.java | 2 +- .../core/SimpleReactiveMongoDatabaseFactoryUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/TestEntities.java | 2 +- .../data/mongodb/core/TestMongoConfiguration.java | 2 +- .../test/java/org/springframework/data/mongodb/core/Trade.java | 2 +- .../mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java | 2 +- .../test/java/org/springframework/data/mongodb/core/User.java | 2 +- .../test/java/org/springframework/data/mongodb/core/Venue.java | 2 +- .../data/mongodb/core/aggregation/AggregationOptionsTests.java | 2 +- .../data/mongodb/core/aggregation/AggregationTests.java | 2 +- .../data/mongodb/core/aggregation/AggregationUnitTests.java | 2 +- .../mongodb/core/aggregation/AggregationUpdateUnitTests.java | 2 +- .../mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java | 2 +- .../data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java | 2 +- .../mongodb/core/aggregation/BucketAutoOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/BucketOperationUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/aggregation/City.java | 2 +- .../data/mongodb/core/aggregation/CondExpressionUnitTests.java | 2 +- .../mongodb/core/aggregation/ConvertOperatorsUnitTests.java | 2 +- .../data/mongodb/core/aggregation/CountOperationUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/aggregation/Data.java | 2 +- .../springframework/data/mongodb/core/aggregation/DataItem.java | 2 +- .../data/mongodb/core/aggregation/ExposedFieldsUnitTests.java | 2 +- .../data/mongodb/core/aggregation/FacetOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/FieldsUnitTests.java | 2 +- .../mongodb/core/aggregation/GeoNearOperationUnitTests.java | 2 +- .../mongodb/core/aggregation/GraphLookupOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/GroupOperationUnitTests.java | 2 +- .../springframework/data/mongodb/core/aggregation/Invoice.java | 2 +- .../data/mongodb/core/aggregation/LikeStats.java | 2 +- .../springframework/data/mongodb/core/aggregation/LineItem.java | 2 +- .../data/mongodb/core/aggregation/LookupOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/MeterData.java | 2 +- .../data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java | 2 +- .../springframework/data/mongodb/core/aggregation/Order.java | 2 +- .../data/mongodb/core/aggregation/OutOperationUnitTest.java | 2 +- .../springframework/data/mongodb/core/aggregation/Product.java | 2 +- .../mongodb/core/aggregation/ProjectionOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/ReactiveAggregationTests.java | 2 +- .../mongodb/core/aggregation/ReactiveAggregationUnitTests.java | 2 +- .../mongodb/core/aggregation/ReplaceRootOperationUnitTests.java | 2 +- .../mongodb/core/aggregation/ReplaceWithOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/SampleOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/SetOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/SkipOperationUnitTests.java | 2 +- .../mongodb/core/aggregation/SortByCountOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/SortOperationUnitTests.java | 2 +- .../aggregation/SpelExpressionTransformerIntegrationTests.java | 2 +- .../core/aggregation/SpelExpressionTransformerUnitTests.java | 2 +- .../data/mongodb/core/aggregation/StateStats.java | 2 +- .../data/mongodb/core/aggregation/StringOperatorsUnitTests.java | 2 +- .../TypeBasedAggregationOperationContextUnitTests.java | 2 +- .../data/mongodb/core/aggregation/UnsetOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/UnwindOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/UserWithLikes.java | 2 +- .../data/mongodb/core/auditing/MongoTemplateAuditingTests.java | 2 +- .../core/auditing/ReactiveMongoTemplateAuditingTests.java | 2 +- .../mongodb/core/convert/AbstractMongoConverterUnitTests.java | 2 +- .../data/mongodb/core/convert/CustomConvertersUnitTests.java | 2 +- .../data/mongodb/core/convert/DataMongo273Tests.java | 2 +- .../core/convert/DbRefMappingMongoConverterUnitTests.java | 2 +- .../mongodb/core/convert/DefaultDbRefResolverUnitTests.java | 2 +- .../mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java | 2 +- .../data/mongodb/core/convert/DocumentAccessorUnitTests.java | 2 +- .../data/mongodb/core/convert/GeoConvertersUnitTests.java | 2 +- .../data/mongodb/core/convert/GeoJsonConverterUnitTests.java | 2 +- .../mongodb/core/convert/LazyLoadingInterceptorUnitTests.java | 2 +- .../data/mongodb/core/convert/LazyLoadingTestUtils.java | 2 +- .../data/mongodb/core/convert/MappingMongoConverterTests.java | 2 +- .../mongodb/core/convert/MappingMongoConverterUnitTests.java | 2 +- .../mongodb/core/convert/MongoConvertersIntegrationTests.java | 2 +- .../data/mongodb/core/convert/MongoConvertersUnitTests.java | 2 +- .../mongodb/core/convert/MongoCustomConversionsUnitTests.java | 2 +- .../data/mongodb/core/convert/MongoExampleMapperUnitTests.java | 2 +- .../mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java | 2 +- .../mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java | 2 +- .../core/convert/NumberToNumberConverterFactoryUnitTests.java | 2 +- .../data/mongodb/core/convert/ObjectPathUnitTests.java | 2 +- .../data/mongodb/core/convert/QueryMapperUnitTests.java | 2 +- .../mongodb/core/convert/TermToStringConverterUnitTests.java | 2 +- .../data/mongodb/core/convert/UpdateMapperUnitTests.java | 2 +- .../data/mongodb/core/geo/AbstractGeoSpatialTests.java | 2 +- .../data/mongodb/core/geo/GeoJsonModuleUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/geo/GeoJsonTests.java | 2 +- .../data/mongodb/core/geo/GeoSpatial2DSphereTests.java | 2 +- .../data/mongodb/core/geo/GeoSpatial2DTests.java | 2 +- .../data/mongodb/core/geo/GeoSpatialIndexTests.java | 2 +- .../data/mongodb/core/index/IndexFieldUnitTests.java | 2 +- .../data/mongodb/core/index/IndexInfoUnitTests.java | 2 +- .../data/mongodb/core/index/IndexingIntegrationTests.java | 2 +- .../MongoPersistentEntityIndexCreatorIntegrationTests.java | 2 +- .../core/index/MongoPersistentEntityIndexCreatorUnitTests.java | 2 +- .../core/index/MongoPersistentEntityIndexResolverUnitTests.java | 2 +- .../springframework/data/mongodb/core/index/PathUnitTests.java | 2 +- .../ReactiveMongoPersistentEntityIndexCreatorUnitTests.java | 2 +- .../springframework/data/mongodb/core/index/TextIndexTests.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Account.java | 2 +- .../springframework/data/mongodb/core/mapping/AccountPojo.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Address.java | 2 +- .../springframework/data/mongodb/core/mapping/BasePerson.java | 2 +- .../core/mapping/BasicMongoPersistentEntityUnitTests.java | 2 +- .../core/mapping/BasicMongoPersistentPropertyUnitTests.java | 2 +- .../data/mongodb/core/mapping/CustomCollectionWithIndex.java | 2 +- .../data/mongodb/core/mapping/DetectedCollectionWithIndex.java | 2 +- .../springframework/data/mongodb/core/mapping/GeneratedId.java | 2 +- .../data/mongodb/core/mapping/GenericMappingTests.java | 2 +- .../data/mongodb/core/mapping/GeoIndexedAppConfig.java | 2 +- .../data/mongodb/core/mapping/GeoIndexedTests.java | 2 +- .../springframework/data/mongodb/core/mapping/GeoLocation.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Location.java | 2 +- .../springframework/data/mongodb/core/mapping/MappingTests.java | 2 +- .../data/mongodb/core/mapping/MongoMappingContextUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/mapping/Person.java | 2 +- .../data/mongodb/core/mapping/PersonCustomCollection1.java | 2 +- .../data/mongodb/core/mapping/PersonCustomCollection2.java | 2 +- .../data/mongodb/core/mapping/PersonCustomIdName.java | 2 +- .../data/mongodb/core/mapping/PersonMapProperty.java | 2 +- .../data/mongodb/core/mapping/PersonMultiCollection.java | 2 +- .../data/mongodb/core/mapping/PersonMultiDimArrays.java | 2 +- .../data/mongodb/core/mapping/PersonNullProperties.java | 2 +- .../data/mongodb/core/mapping/PersonPojoIntId.java | 2 +- .../data/mongodb/core/mapping/PersonPojoLongId.java | 2 +- .../data/mongodb/core/mapping/PersonPojoStringId.java | 2 +- .../data/mongodb/core/mapping/PersonSimpleList.java | 2 +- .../data/mongodb/core/mapping/PersonWithDbRef.java | 2 +- .../data/mongodb/core/mapping/PersonWithObjectId.java | 2 +- .../springframework/data/mongodb/core/mapping/PrimitiveId.java | 2 +- .../core/mapping/event/AbstractMongoEventListenerUnitTests.java | 2 +- .../data/mongodb/core/mapping/event/AfterSaveListener.java | 2 +- .../core/mapping/event/ApplicationContextEventTests.java | 2 +- .../mapping/event/ApplicationContextEventTestsAppConfig.java | 2 +- .../core/mapping/event/AuditingEntityCallbackUnitTests.java | 2 +- .../core/mapping/event/AuditingEventListenerUnitTests.java | 2 +- .../mongodb/core/mapping/event/LoggingEventListenerTests.java | 2 +- .../mongodb/core/mapping/event/PersonBeforeSaveListener.java | 2 +- .../mongodb/core/mapping/event/SimpleMappingEventListener.java | 2 +- .../springframework/data/mongodb/core/mapping/event/User.java | 2 +- .../core/mapping/event/ValidatingMongoEventListenerTests.java | 2 +- .../data/mongodb/core/mapreduce/GroupByTests.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceOptionsTests.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java | 2 +- .../data/mongodb/core/mapreduce/MapReduceTests.java | 2 +- .../data/mongodb/core/mapreduce/ReactiveMapReduceTests.java | 2 +- .../data/mongodb/core/mapreduce/ValueObject.java | 2 +- .../data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java | 2 +- .../data/mongodb/core/messaging/ChangeStreamTests.java | 2 +- .../data/mongodb/core/messaging/CursorReadingTaskUnitTests.java | 2 +- .../core/messaging/DefaultMessageListenerContainerTests.java | 2 +- .../messaging/DefaultMessageListenerContainerUnitTests.java | 2 +- .../data/mongodb/core/messaging/SubscriptionUtils.java | 2 +- .../mongodb/core/messaging/TailableCursorRequestUnitTests.java | 2 +- .../data/mongodb/core/messaging/TailableCursorTests.java | 2 +- .../data/mongodb/core/messaging/TaskFactoryUnitTests.java | 2 +- .../data/mongodb/core/query/BasicQueryUnitTests.java | 2 +- .../springframework/data/mongodb/core/query/CriteriaTests.java | 2 +- .../data/mongodb/core/query/CriteriaUnitTests.java | 2 +- .../springframework/data/mongodb/core/query/FieldUnitTests.java | 2 +- .../springframework/data/mongodb/core/query/IndexUnitTests.java | 2 +- .../data/mongodb/core/query/MetricConversionUnitTests.java | 2 +- .../data/mongodb/core/query/MongoRegexCreatorUnitTests.java | 2 +- .../data/mongodb/core/query/NearQueryUnitTests.java | 2 +- .../org/springframework/data/mongodb/core/query/QueryTests.java | 2 +- .../org/springframework/data/mongodb/core/query/SortTests.java | 2 +- .../data/mongodb/core/query/TextCriteriaUnitTests.java | 2 +- .../springframework/data/mongodb/core/query/TextQueryTests.java | 2 +- .../data/mongodb/core/query/TextQueryUnitTests.java | 2 +- .../data/mongodb/core/query/UntypedExampleMatcherUnitTests.java | 2 +- .../springframework/data/mongodb/core/query/UpdateTests.java | 2 +- .../data/mongodb/core/schema/JsonSchemaObjectUnitTests.java | 2 +- .../data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java | 2 +- .../data/mongodb/core/schema/MongoJsonSchemaTests.java | 2 +- .../data/mongodb/core/schema/MongoJsonSchemaUnitTests.java | 2 +- .../data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java | 2 +- .../mongodb/core/script/ExecutableMongoScriptUnitTests.java | 2 +- .../data/mongodb/core/script/NamedMongoScriptUnitTests.java | 2 +- .../data/mongodb/core/spel/ExpressionNodeUnitTests.java | 2 +- .../mongodb/core/validation/CriteriaValidatorUnitTests.java | 2 +- .../springframework/data/mongodb/gridfs/AntPathUnitTests.java | 2 +- .../data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java | 2 +- .../mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java | 2 +- .../data/mongodb/gridfs/GridFsResourceUnitTests.java | 2 +- .../data/mongodb/gridfs/GridFsTemplateIntegrationTests.java | 2 +- .../data/mongodb/gridfs/ReactiveGridFsTemplateTests.java | 2 +- .../data/mongodb/monitor/MongoMonitorIntegrationTests.java | 2 +- .../org/springframework/data/mongodb/monitor/Resumeable.java | 2 +- .../data/mongodb/performance/PerformanceTests.java | 2 +- .../data/mongodb/performance/ReactivePerformanceTests.java | 2 +- .../repository/AbstractPersonRepositoryIntegrationTests.java | 2 +- .../org/springframework/data/mongodb/repository/Address.java | 2 +- .../mongodb/repository/ComplexIdRepositoryIntegrationTests.java | 2 +- .../org/springframework/data/mongodb/repository/Contact.java | 2 +- .../data/mongodb/repository/ContactRepository.java | 2 +- .../mongodb/repository/ContactRepositoryIntegrationTests.java | 2 +- .../repository/ConvertingReactiveMongoRepositoryTests.java | 2 +- .../springframework/data/mongodb/repository/Credentials.java | 2 +- .../repository/MongoRepositoryTextSearchIntegrationTests.java | 2 +- .../java/org/springframework/data/mongodb/repository/MyId.java | 2 +- .../org/springframework/data/mongodb/repository/Person.java | 2 +- .../data/mongodb/repository/PersonAggregate.java | 2 +- .../springframework/data/mongodb/repository/PersonExcerpt.java | 2 +- .../data/mongodb/repository/PersonRepository.java | 2 +- .../mongodb/repository/PersonRepositoryIntegrationTests.java | 2 +- .../repository/PersonRepositoryLazyLoadingIntegrationTests.java | 2 +- .../mongodb/repository/PersonRepositoryTransactionalTests.java | 2 +- .../springframework/data/mongodb/repository/PersonSummary.java | 2 +- .../data/mongodb/repository/PersonSummaryDto.java | 2 +- .../data/mongodb/repository/ReactiveMongoRepositoryTests.java | 2 +- .../data/mongodb/repository/ReactivePersonRepository.java | 2 +- .../repository/RedeclaringRepositoryMethodsRepository.java | 2 +- .../mongodb/repository/RedeclaringRepositoryMethodsTests.java | 2 +- .../repository/RepositoryIndexCreationIntegrationTests.java | 2 +- .../mongodb/repository/SampleEvaluationContextExtension.java | 2 +- .../mongodb/repository/SimpleReactiveMongoRepositoryTests.java | 2 +- .../org/springframework/data/mongodb/repository/SumAge.java | 2 +- .../java/org/springframework/data/mongodb/repository/User.java | 2 +- .../data/mongodb/repository/UserWithComplexId.java | 2 +- .../data/mongodb/repository/UserWithComplexIdRepository.java | 2 +- .../data/mongodb/repository/UsernameAndPassword.java | 2 +- .../data/mongodb/repository/VersionedPerson.java | 2 +- .../mongodb/repository/cdi/CdiExtensionIntegrationTests.java | 2 +- .../data/mongodb/repository/cdi/CdiPersonRepository.java | 2 +- .../data/mongodb/repository/cdi/MongoTemplateProducer.java | 2 +- .../data/mongodb/repository/cdi/RepositoryClient.java | 2 +- .../data/mongodb/repository/cdi/SamplePersonFragment.java | 2 +- .../data/mongodb/repository/cdi/SamplePersonFragmentImpl.java | 2 +- .../data/mongodb/repository/cdi/SamplePersonRepository.java | 2 +- .../repository/config/MongoNamespaceIntegrationTests.java | 2 +- .../config/MongoRepositoriesRegistrarIntegrationTests.java | 2 +- .../config/MongoRepositoryConfigurationExtensionUnitTests.java | 2 +- .../ReactiveMongoRepositoriesRegistrarIntegrationTests.java | 2 +- .../ReactiveMongoRepositoryConfigurationExtensionUnitTests.java | 2 +- .../lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java | 2 +- .../repository/config/lazy/ClassWithNestedRepository.java | 2 +- .../config/lazy/NestedMongoRepositoriesJavaConfigTests.java | 2 +- .../data/mongodb/repository/custom/ComposedRepository.java | 2 +- .../custom/ComposedRepositoryImplementationTests.java | 2 +- .../data/mongodb/repository/custom/CustomMongoRepository.java | 2 +- .../mongodb/repository/custom/CustomMongoRepositoryImpl.java | 2 +- .../repository/custom/CustomReactiveMongoRepository.java | 2 +- .../repository/custom/CustomReactiveMongoRepositoryCustom.java | 2 +- .../repository/custom/CustomReactiveMongoRepositoryImpl.java | 2 +- .../custom/CustomReactiveRepositoryImplementationTests.java | 2 +- .../repository/custom/CustomRepositoryImplementationTests.java | 2 +- .../data/mongodb/repository/custom/RepositoryMixin.java | 2 +- .../data/mongodb/repository/custom/RepositoryMixinImpl.java | 2 +- .../mongodb/repository/query/AbstractMongoQueryUnitTests.java | 2 +- .../repository/query/AbstractReactiveMongoQueryUnitTests.java | 2 +- .../repository/query/ConvertingParameterAccessorUnitTests.java | 2 +- .../query/MappingMongoEntityInformationUnitTests.java | 2 +- .../query/MongoParametersParameterAccessorUnitTests.java | 2 +- .../data/mongodb/repository/query/MongoParametersUnitTests.java | 2 +- .../mongodb/repository/query/MongoQueryCreatorUnitTests.java | 2 +- .../mongodb/repository/query/MongoQueryExecutionUnitTests.java | 2 +- .../mongodb/repository/query/MongoQueryMethodUnitTests.java | 2 +- .../mongodb/repository/query/PartTreeMongoQueryUnitTests.java | 2 +- .../repository/query/ReactiveMongoQueryExecutionUnitTests.java | 2 +- .../repository/query/ReactiveMongoQueryMethodUnitTests.java | 2 +- .../query/ReactiveStringBasedAggregationUnitTests.java | 2 +- .../query/ReactiveStringBasedMongoQueryUnitTests.java | 2 +- .../repository/query/StringBasedAggregationUnitTests.java | 2 +- .../repository/query/StringBasedMongoQueryUnitTests.java | 2 +- .../data/mongodb/repository/query/StubParameterAccessor.java | 2 +- .../support/IndexEnsuringQueryCreationListenerUnitTests.java | 2 +- .../repository/support/MongoRepositoryFactoryBeanUnitTests.java | 2 +- .../repository/support/MongoRepositoryFactoryUnitTests.java | 2 +- .../support/QuerydslMongoPredicateExecutorIntegrationTests.java | 2 +- .../repository/support/QuerydslRepositorySupportTests.java | 2 +- .../support/ReactiveQuerydslMongoPredicateExecutorTests.java | 2 +- .../mongodb/repository/support/SimpleMongoRepositoryTests.java | 2 +- .../repository/support/SimpleMongoRepositoryUnitTests.java | 2 +- .../support/SimpleMongoRepositoryVersionedEntityTests.java | 2 +- .../support/SimpleReactiveMongoRepositoryUnitTests.java | 2 +- .../SimpleReactiveMongoRepositoryVersionedEntityTests.java | 2 +- .../support/SpringDataMongodbSerializerUnitTests.java | 2 +- .../data/mongodb/test/util/AfterTransactionAssertion.java | 2 +- .../springframework/data/mongodb/test/util/AssertErrors.java | 2 +- .../org/springframework/data/mongodb/test/util/Assertions.java | 2 +- .../data/mongodb/test/util/BasicDbListBuilder.java | 2 +- .../springframework/data/mongodb/test/util/CleanMongoDB.java | 2 +- .../data/mongodb/test/util/CleanMongoDBJunitRunListener.java | 2 +- .../data/mongodb/test/util/CleanMongoDBTests.java | 2 +- .../springframework/data/mongodb/test/util/DocumentAssert.java | 2 +- .../data/mongodb/test/util/EnableIfMongoServerVersion.java | 2 +- .../data/mongodb/test/util/EnableIfReplicaSetAvailable.java | 2 +- .../data/mongodb/test/util/MongoServerCondition.java | 2 +- .../springframework/data/mongodb/test/util/MongoTestUtils.java | 2 +- .../springframework/data/mongodb/test/util/MongoVersion.java | 2 +- .../data/mongodb/test/util/MongoVersionRule.java | 2 +- .../org/springframework/data/mongodb/test/util/ReplicaSet.java | 2 +- .../mongodb/util/json/ParameterBindingJsonReaderUnitTests.java | 2 +- 853 files changed, 853 insertions(+), 853 deletions(-) diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java index 4af306a4db..c7df157f63 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java index d647ac6950..5694416f3d 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java index 3b9efee29a..a29fb51e3e 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java index 72119225e8..4c09f1a166 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java index 2f271527a5..e6d728dbdc 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java index bcd9de082e..19e7987ee2 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java index 59eb58e342..bc43cb5ded 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java index 678f5c7f59..4435f4d4e7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java index 14a4e39cd8..46c1c43546 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java index 4ede50ce00..81d0955f0a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java index bd3cbfe20a..4d5831dd4d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java index f05eff0739..67ca617d13 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java index 88ddc7e86d..4167250634 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index 2311c00098..6e3faac9b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index 50a9871899..7ad7d8f817 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java index 8c2c2b9547..6ebd5d9518 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java index d264f4e9cc..47cd65a1c8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java index ff41b171cf..746a769e22 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java index 43f0289d61..80fc02eeab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java index ac50328917..601582702a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java index 9067b74ece..37a5b3d0f6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java index cb19f15ba9..fd16e408ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java index 9bd0fbfe06..8792e169cc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java index 50f77d3f29..621a5389e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java index 1482cde3c0..f32d0f593e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java index 25161214eb..fc2079ba8c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index c5f10730f3..6627cbb045 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java index bed47de650..a5eadefd02 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java index 1b92254902..2e550dfba8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java index 686df220d9..3bb71c86ab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java index 4eaf613d0b..82d9c4fa0a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java index fdb7d3479e..d93c11466d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java index 78545cd39e..1b03d777bc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java index bdbd7bd3c5..adbf2e771d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java index ba1bfd5332..fb3ac7408e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java index a87aa30a55..f842b9b738 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java index c08332390d..8aa0a04887 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index eaa4c6b012..ea137756f9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java index 1ba95a407a..39f17c4142 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java index e0048a6d3c..272b4f1638 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java index 4c2e55416f..93248e2f3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java index 87868fa502..2516ca70e4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index 36c2544c48..aa85041d9e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java index c489547d80..65aa04745f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java index a46abcd4fb..87174f28c0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java index 0317d25fd5..2865248eac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java index 84a388415d..141c874ffc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java index 27d6ecf394..0ce3f00012 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java index c8984e13a3..e67773c1fc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java index 3d8c13a1ce..11b6ff3e0f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java index ff14ee61a2..8e1d3523c5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java index fc6f69a125..535e40a216 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java index d82df3e7b8..b5e51613a7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. 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 684bdc3b52..d9338e0f3c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java index 4504597490..ee2c7368a8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java index 52bec22039..a9ce9427cf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java index 63ee762f3f..d828e962e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index 09bb2bb9a5..a1e0f21550 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java index c1012080ab..de1896b310 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java index 9f47619f96..f7a0a1658f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java index dbfc2a3b5b..2ec7c14c95 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java index 71d59993b8..53e217f3eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java index 574ae14441..459792e11a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java index c712cfb60f..1a002392b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index 343e83a1ee..5382b70c0c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java index 64bf134feb..329989818e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java index df0a24a20a..76ff13a02a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index 26454e7e2e..9bf2246b95 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java index 06fce43e51..d27fdfac7b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java index c158be949b..2827f770cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java index 5ec1b78cfe..a22625f7ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java index dca70ef331..877295f815 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java index 07cb70fbbc..57e9d38cc4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java index 6688ff23ec..eb031c0353 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java index 370fb5bc7c..edba892a03 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index efd8d0568f..414a1b7dc2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java index 09bac18ba3..0d84c56f9a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java index c9adf1f841..d7fac7ab97 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java index 1da434326e..379015cd8a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java index 92b3fa3975..ddf1b4e373 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java index 20fb73ca27..7fbd49359e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java index 63f48c20b1..ddd1216b3c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java index 093a1d900c..7e574c6944 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java index 474670b2a4..72b351fc41 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. 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 815a68994d..fdc7247ee7 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 @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java index 9db8cca15d..c47cc04941 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java index 627cca6ee0..9662e31b2c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java index fe1d757f3c..8a92d39e5d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java index caf0134ddf..f28113cc5a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index fccb8c0251..3f207eba02 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java index 84c3941883..8b2b552c7a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java index 10e0d3fe7e..7451152203 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index e607f0e3b1..9915656b5d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java index f09759039b..555913c548 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index 695bec3bcc..e06e83f61a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java index a20b353e08..2757ba2c31 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index ccc06584f6..a93670cd03 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. 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 8194262366..abdf580570 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java index 3ca684cac4..6afb8e9405 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java index 43d1c46042..e2a4743a40 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java index 1079a8b9f4..ce512b2615 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java index 89ca7f1173..eab988c5ab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java index e042b606db..691a6e256c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java index 133a11335b..f59ed5e60e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java index 309c2b7821..cc36e0358b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index 3ca84e8c67..793c73a11c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java index 8957d93472..b05204a7eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java index efb1d8a35c..631568e4a3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java index 5eff2e1a28..c9801da417 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java index 85bb3766f4..e0fc029bb6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java index 8d6fbe6c4e..20d22204ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java index 839aefcc4d..4f9d5669fc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java index 6458e45cd7..06ef8307c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java index 0b63352126..4809761706 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java index bd466a4b8a..007cdeb7b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index c3d230b7bc..56e5b088b2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 47b272b79d..f3c37d1265 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java index e8b243c804..1e51dec359 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java index 23a1578a0f..62835c0231 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java index d69f79eaba..084c2ce9f5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java index d4016f4907..8babbe3ae0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java index 711a20cb32..6c7e6b6252 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java index 22c1ad6899..ff1aede220 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java index 3e46c0411e..fa2e16b082 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java index 0dafcee5bb..fd5e0fba85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java index adf02e4c5c..5c58121f77 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java index 236ff91c85..3b03afa5ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java index e9059955bd..d5d306e877 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java index 4ed67a9c4a..cdfeaa5091 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java index f7effcf38a..4d91dcd356 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java index f47bd9c48d..f2434735a3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java index 01505189bc..ceffe9e8d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 70d2987ca7..7229c8339a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java index dd0ac96be3..5fb2e8278d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java index 3e950f110b..a89905e668 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java index 54c973ee3a..28e8b63f61 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java index 932fbaf6b2..2b8a7171e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java index e16d398cd3..56940180ad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java index 7f57f35b8d..eebba56434 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 149e9fc2c3..381fa15ab3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java index 034b1a1f92..2e6cd72575 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java index c6b9838339..23bb50e364 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index 0803eb0f76..e8201e4ba4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java index bd78316b5c..ae5b959fbd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java index 2750549669..ee1b3806b3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java index 8e5b7d1503..cbab756934 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java index dd84973b29..c9ea533fae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java index 4b750a3eb8..75c9e9a553 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java index 3780b4d242..c39e79f54e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java index 5e2d42b21b..07bfebd701 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java index d112724bff..7d273dc751 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java index 5560e0d4aa..ab837f4376 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java index 3c190ee5f2..21d2d24be5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java index 3e32433880..d802fa4d12 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java index 6c070160a8..ea020d2597 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java index 0aca376876..2e0ba33071 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java index acec863b2d..1daeafa32d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java index 5fad7274ca..de8752d589 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java index 6295cd45ed..ca2eaf782f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java index b5fa88c6d8..0cee343733 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index aceb8759e7..d3efbd299c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java index 5a6dce072f..b221e9ba2d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java index c855ada17a..67b19c53fa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java index 099e49101e..05913eb60d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index f91cda9f9d..604ffab2c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java index c6df7a8122..0aef6af3cd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java index b0b29ca731..11d6407b60 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java index 911b69f2e1..b941b801a4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index 85f83acfc1..a0ad3b46ff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java index dd96750f77..af81ca3de9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index 00c7bbc22b..7eed7a0683 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java index 81454326bc..e341cf4ecf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java index af7a2d3b92..a3de07be17 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index 0c7933eeca..61657450ae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java index bb8922fb9c..a6c20e61c6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java index e5080420f2..436bb3ab99 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java index 761c9eef89..cd3169e4f3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java index 74d7fc8b76..a21223ee35 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java index b9d04a9495..3187648450 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java index 75a7ff41df..59a5eddcf9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java index 03c6660a71..19427df08c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java index f2db18ad4e..5a62b5c504 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java index 0f9aece97d..7bb36f9999 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java index d50c5bd91b..b6d90aeb0e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java index 0483a2f889..2f0569bd47 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java index f2bfdbc072..e4f14fe935 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java index 4b4336aaad..04ddc97115 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java index b95d653bf3..437426db49 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java index d1278add38..e3a66c020b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 0c6b75574f..0a4d99325b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java index 9582101cb4..5bd182ca94 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. 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 b166815615..fe3ac71fbd 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java index 8ec2d42659..5709976176 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java index 238601768e..e3b1d98925 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java index 788dde7b75..1b00add6b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java index 3f88d5e055..8b1800bb3e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java index ba189d0b94..1448544f27 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. 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 4c5b88ea01..05c4c0b5d1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index 8f51e42754..9269e09b8d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java index 70d3673653..0db28c31f0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java index 3fefb585d4..7e56590459 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java index 6afecba935..884a1a96a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java index dbe8669100..d2896280e0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java index 5394c45c30..83069f38d7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java index d8493c513e..c11ebd80fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java index dd3c20e0e5..f9262f8b3b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java index 672f5bd112..6af70e6c2d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index efb3368fca..81b425b9af 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java index 964fbcff8c..5cf86823c5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java index 669e7b18fd..c449c715e1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java index 4dd16aead9..8e1a3c9233 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java index 34f6dacb62..46f2341d19 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java index 5c39c6ad9a..afb2370f3e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java index 514b056a02..4acb111c3d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java index 2d6835c760..49d886ddcc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java index b3db0bb2fe..3bd81c207e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java index 30e6c73d7a..32f4e26ecf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java index fbd9f9d140..3086df003d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java index 6d97ac8a28..0f68ac4f45 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java index 79ad5073c2..6ce0bdc1e9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java index c28549decf..4fd4bc6100 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java index f68a61d5ce..de137b21bf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java index 1d57079cba..4dae271d33 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java index c7f702691d..9f76746b60 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java index 64fa849cdc..be56df5e9b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java index 506e1c7428..e0f7d4da98 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java index 7404dc7cbd..1e4f85cd5a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java index 3c68eff4a0..071b8f48cc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java index 1a28bc1d60..40bb8f0788 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java index 3f7b1a4cd0..3637909214 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java index d0e041bac6..2bc2c99ffa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java index 746c4833f6..28d15553c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java index e41eb35a2c..dc5d5d60ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java index 3cd30a3d34..02ff07d658 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java index 20468c5d31..d3c923c42f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java index 8695f08c53..7ea6fbbd23 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java index eed28488b8..a64257af22 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java index 0ce8d175cb..ec686a6189 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java index 89b6a90885..cb84c72ddf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java index fdf418b9c8..c948898d00 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java index 5549260f66..e4fb9452cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java index 6aba6dd01b..109270ec04 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java index 64d6e43257..00a1315760 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java index 9f9c2323b8..ab4428b3f1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index b0e997c43c..fcaf105678 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java index 37defd769c..0286095902 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java index af7c935f25..68977a99eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java index 29cdf656dc..1bed0a797f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java index 59d55dd4a0..101694f4d6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java index 9cba42c945..58d510be8b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index 3f41090396..f24ad0d78f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 2acc48cf7a..1bb0cf83a9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java index c6cf2b4122..662b6bee35 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java index 1ca71e7fd5..3bbbb3d7fe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java index eb9a6d5190..e806477e4e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java index c91e58bb2b..2fd2218fc3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. 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 f550e8a588..3fd884e0fe 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java index e51ac32d9f..0b50ee7b7f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java index 6b52b0d98f..15241cacc5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index 434201ab28..b55fb3cfa4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java index 35fcf1ef4b..8d6aaa1504 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index 706e0277ca..7d6db37c0f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java index 39163775de..27a4ac9e5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java index 38d4e7859c..a21a976eb5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java index d057ff1a66..e1378ec953 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java index 0f4c0097be..2fbfbf5175 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java index 4155f5ba35..4eb6a22117 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java index 95df315e94..29a1b58552 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java index 1c5f8cdbed..1f9c07766f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java index 95318b560c..a82041802e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java index 30d9ffac59..0d25bb2a46 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java index 85a220a5c9..2b1b0d3f78 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java index c942d1c308..c8a43c1939 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java index 854fc4864b..c5e2366f23 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java index 78ec028496..f1ed6db97d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java index feadc0a118..cdb0e2424f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java index cc376bd214..601676043d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java index d035daba37..b7c8a694ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java index 4fbfaa8879..58150baf94 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java index 0a4ababd93..368257067d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java index ba9a086d59..a82ca01b93 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java index fbd37c8661..3f50ac2916 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java index 20fecd848c..d53ae30e19 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java index 0520a14eaf..8fc42d2bc3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java index e81a44f42d..0c5455a9d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java index 02bb4b04ca..546814efd6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java index 39e89f9404..f80f2b858d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java index df661ffc4c..604528fb25 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java index f98dc48531..979f6326db 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java index 77c1ff421d..3aee394e8a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java index 8265aa13f8..71053ff0a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java index 14c79a9e6d..62a639799c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java index c87f0ffa92..f3fa017943 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java index a9292c8e00..c9f367614a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java index 1f52821cef..bdcddad854 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java index 6636a44620..510aac2760 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java index 8587563ffa..224e4a48a8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java index 0c6492a773..6fdb0496d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java index 636ee804de..320ba5ec6a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java index e24a108956..1dd267db4f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index 8ee910e118..a9d9bde161 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java index c81bad6c16..0c1bb60ec7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java index 7eecc79fdb..9425a64a7b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java index c61d0decca..28ddf348fd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java index 9d6b1782ab..eb37ab93c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java index 65f23e3037..8a6b740451 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java index 1f33041450..2b785ff524 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java index c7a9a51fe4..4b87ca81b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 7d57f16f54..99dcb21e15 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java index c164d39c01..2913fdbbfe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java index 45b2d9544d..35b7714968 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java index afcff140c5..b18e7831e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. 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 1a5a73cf31..3bff1fb6b3 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-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java index f78bb850d6..5958b3e3ee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java index 5901375110..f81b561726 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java index 4a9a309c6a..f37347efca 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. 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 2d47d39aba..b29763564b 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-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java index b02385a071..916858e7f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java index d1c432a07d..ed51e4b400 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java index 5afd061470..66aca4cf0e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java index 8eeb787509..0f1e40550e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java index 141da14a7d..5701b276de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index b8c1cb6f83..4957bb5d50 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java index 32784f4431..05660e7d0f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java index 40aa5c7948..cff333b766 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java index dc52924f8c..18aa0b355b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java index 3b46d6b5fe..ef6d0f639c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java index 5f0421272c..6ea9c06497 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java index 3bd149c53a..d13752820d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java index f439c94960..b60c52cd25 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java index af492337cf..fe1e13ab39 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java index dfa584cc6c..e3d05d419f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java index a0ecfe19bf..cb076c42f3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java index d02dd7966f..029d718c90 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java index 73b1ccf8e0..560691a3d6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java index aea2f914f2..93270f2b5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java index a42f368a3e..978b6e9c95 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java index a86ed75c73..68c0bb10f7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index dcc351fa0f..8bf6a8f98b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java index 6cd8ce9318..3bee4d7905 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. 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 index 594e87c59a..fa76e1d473 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java index c6f4936bc2..aff1920291 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java index e52e667596..80bb6de707 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java index 2ef8f0fc18..0b9d131b01 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java index 280ad20980..df2ef261bb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java index ff2a33bf57..19cd8ea18c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java index 0bb0b1fdde..e793f84c19 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java index de364c9279..3e303b68c0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java index 80e6d94278..27a337ff46 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index b5997d512e..abda4e6178 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java index 99d3d1125d..2fa73a303a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java index 19c646e214..d5db0c1300 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 74e398ee59..5cc4524837 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java index 9da9221477..9170da7cc5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java index fb40dad10c..173ab24002 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index 48e599ca43..3537b146ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java index 0ff0829261..0366bb761f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java index 85bad3e70b..2819aed42b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java index ba7da4db36..1cb0a4c995 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java index 0bdb4e86e4..22e9b985f1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java index 88502cb177..b56ccdb614 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java index 239ed9f003..ea2c783846 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java index cde524252f..6ec809f928 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java index 3ef8f069ce..b959004af5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java index 3ab17bcd46..0ec3e7ee69 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java index eea5b01188..5b6c908b6d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java index bdbaaba83f..8c0d5c25cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java index 49de6afaba..c41ee5ba93 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java index 0df1ba751e..73fcabb4ad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. 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 704cf9aace..01977287c6 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 @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java index 116f914b2b..664c5ca8bc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java index 4d576471b0..bf23f33801 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java index 0bc3e1618c..0ce7841679 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java index 8029fa640b..ff78e7282c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java index cb94cd0ade..c018fa29bc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java index 7134995e63..576013fdfe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java index 8ffbf5de79..63d6fbaaa6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java index f74da9b406..dced7913c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java index ef653d8b2f..5ba8dcf8e1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java index b7c378d477..8923d08f48 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java index 2929efcc16..60ec8f4c5b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java index fa8b7df2cd..af01fb2498 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java index 35286eb71b..b4335bc3e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java index a003b057e0..936ad35265 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java index b355c37572..f3c7167b78 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index 6b281d3d2d..81b8305ee2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index 49cfee36c9..a514d3a2d9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java index ef41d58f53..e07a85e1d6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index 6547159b51..411674e269 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java index 1ede41714f..7e05ad95fd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java index 4ce713e150..a7c2a9a44c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java index 22242a4f90..9dd2bdc12d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java index 170c4943dd..44cf42f9d4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java index 43bdfcc22c..1dc153398b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java index e7800498a2..a33b5df063 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java index 5f26803ddc..483b806939 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java index 7ed2d4e17c..529d12307b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index cbd8eb0824..be422616e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. 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 a8d244424d..466171c2fd 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java index 7a3f3e4b80..8063c17b24 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java index 672afb9d26..d08e1a87ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java index 9c32611349..f95d5cf5ef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 4a8e7e311a..d3b3f186f0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java index 471960df22..391157e355 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java index f5af831a7d..0bce40c3cd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java index bfa65ca1e1..347df2fd22 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index 75c88961bb..b84fca368b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java index fffb35e159..09a5892e53 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java index a413ee3526..9709874fe6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index 34b54f826d..ff84452d8a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java index 8a33392bca..0703c33ecc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java index 9f81af2e1f..426ba97fad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java index 76bcd327f5..9849dea3a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java index ba7355cdcb..10033c1ead 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java index c3d22bd8ae..1cbccff768 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java index 155435f52e..040f2dee77 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java index 79b8b33bcb..ffbc39d00d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java index 6020077aef..95f8dc4fd2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java index 137d339d5c..10962ce279 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java index e4f8218930..6bde6ca208 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java index 94b969d855..dbaa44900d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java index 2b386e045c..e329814780 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java index 5529a1a7da..7f5c87c585 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java index 5bbd545264..107e268ee8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java index 58bafbcc97..091dbb79c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java index 2e49a3f960..8d5cdcb46c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java index 6773e44882..dfbf7acbbd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java index f77b2913a0..85ffd3f8e0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java index 49e8ca4101..d253c86420 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java index 1a54f5e35b..9d598be37a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index 2ad380c785..8244e5b3c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index eec5c2c154..23f9ba65e0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java index ef1ef06ada..43c9f2339a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java index c55cf93d1a..e81b072b8d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index c7dc4da370..3e6f6887ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java index 5cdab3bdc7..7edd8f2128 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java index 74f8f68e2c..0511673fd2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java index cabf3b7ee9..042060c321 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java index 0de9eac29e..e02c2d3640 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java index 20fba1b4cd..e074411238 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java index 2b3bb13778..a967cd8853 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java index 4a5eb845d0..3e9fd396b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java index c649afcab6..64c32360cc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java index 0d919669d0..d2ce700751 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index a70b65bbff..baffcaf8cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index ec334413d9..f524e14598 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2019 the original author or authors. + * Copyright 2008-2020 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java index d6974b64a4..c99e0bc138 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java index 5226cf1e95..a1dd589558 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java @@ -1,6 +1,6 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java index 87403e68aa..48450f1416 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/example/first/First.java b/spring-data-mongodb/src/test/java/example/first/First.java index 08a7343d53..165ca09e8c 100644 --- a/spring-data-mongodb/src/test/java/example/first/First.java +++ b/spring-data-mongodb/src/test/java/example/first/First.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/example/second/Second.java b/spring-data-mongodb/src/test/java/example/second/Second.java index 54fbab8151..d238c90a48 100644 --- a/spring-data-mongodb/src/test/java/example/second/Second.java +++ b/spring-data-mongodb/src/test/java/example/second/Second.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java index bebd844f1b..d1d92aaca9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java index 0ddfc86507..37a7ac3ca0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java index e5bd71134a..7ceac601e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java index d50cdd9149..fb3d11b7bc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java index 6acc3f046d..a0feccb797 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index 1a4aa79f26..8b3ef1f818 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java index 29a7a432c8..85711d8344 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 7df685cc7d..0fc5425063 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index 931d906135..862894f734 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java index a9c3c33180..34414ae7c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java index ea80df1c4b..20e37c5c63 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java index 9e047d6823..14712ebcfd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java index 1e386988a0..58d8f7b213 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/CustomMongoTypeMapper.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/CustomMongoTypeMapper.java index 0784daa106..866cd788d8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/CustomMongoTypeMapper.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/CustomMongoTypeMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java index 1ace056945..5ce8e2c3c2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java index d7a92b4f0d..5518190509 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java index a54f16f2dc..eb3f2220cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserValidationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java index e1d5b41f32..b4cdc51f9d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java index 2e3d303cee..f11232506e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java index d2574e89f2..17e2ebc686 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java index 257c34ecc3..63f97dca37 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 95b19958e0..1195e78962 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java index 172f6309f0..65b0b2c54a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index 835409c4b7..4b2cedeb00 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java index e0f16b9498..13afa1ec98 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index 31b649b09c..5c52460a11 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java index 4e640c141f..3053e955c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java index 21796ced46..d07ef99225 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java index 718644b978..ade0f678a1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java index 6d1267f648..ad937d3d39 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/AuditablePerson.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/AuditablePerson.java index 015f247178..438c7062aa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/AuditablePerson.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/AuditablePerson.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java index b0a6ba2503..2f03056ce7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index dcdb60935b..3cc48a5c89 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java index 421e033aa2..4db0adf31a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java index 4eb14a67c8..3161608576 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java index 648b2b654c..48b668b6ba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java index 13547aae83..03cadacf12 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 2f7aac3f5e..9d1de31cf1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java index d9f548bdd3..3ccf2403e8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java index 3131ea3ea7..8f215f66a0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index a8b79b24ca..7205794af1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java index 5477de09eb..7659f495f0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java index ea1f178efa..25060624d9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java index 410adfe0ed..0bac222ec1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DocumentTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DocumentTestUtils.java index 1df6a2013d..b4cfe55eaa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DocumentTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DocumentTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java index bb45f01640..23bf06549f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java index 21666ff64c..34fa6a6da4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java index d2ebb4883c..57685872e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java index c587e4819f..dfe871d13c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java index 036d3d2f13..cdc66c884c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java index b12cdacf50..a638730ba6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java index 4310ca64e5..878eb56ee0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Friend.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Friend.java index be1b48f9b2..ab79c5dc9d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Friend.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Friend.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java index 9237db04c1..a9424c1321 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java index 7a1698b310..669f41fb13 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java index 62e9c6abfb..92f3b304ae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. 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 de77ee6b0f..c2017e3251 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 @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java index 5f251e6519..de5be15a25 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java index b4a4734854..4e141f171a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java index c701e7e058..e9596901a6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java index 1a469bb2c1..3acd334f5d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java index 69cc26f8ae..9ff6d57bac 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java index 8950571c0c..29e1346eb8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java index ad7d9a8234..5f3cdf6d69 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java index 3477a598a0..cfffce144f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index ea74dabf22..bc1ae71c5b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index da8ab558ee..10cff86d06 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 89d808183a..0a93c42c21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index 27e33eb788..2f46f87d6d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. 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 index 1983634d06..8a2da30c0b 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java index 5e74309c05..27be2abfce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Person.java index 8cabf50871..3c92bdd933 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Person.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Person.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java index 4290d75f64..bab760d69b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java index c5cbb7beab..5e1ad44718 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithAList.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithAList.java index dbf32eca24..c8d50d1390 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithAList.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithAList.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveInt.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveInt.java index 2cd233e6a8..1781353c59 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveInt.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveInt.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveLong.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveLong.java index be0a7e4400..f20e2b386f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveLong.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfPrimitiveLong.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeBigInteger.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeBigInteger.java index 0a56f5baa5..7032279a8b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeBigInteger.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeBigInteger.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeInteger.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeInteger.java index c071200681..e0b673ef5a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeInteger.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeInteger.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeLong.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeLong.java index ae3ef0e727..7bce21a38c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeLong.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeLong.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeObjectId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeObjectId.java index cbc136ae4d..efa5990010 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeObjectId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeObjectId.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeString.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeString.java index f2658c6f51..f3d769186f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeString.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeString.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeUUID.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeUUID.java index bb6e9c28d0..4f0c1e911f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeUUID.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithIdPropertyOfTypeUUID.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java index f1933d7552..de260326e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java index 08f2a916f8..d55718dd7b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeObjectId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeObjectId.java index 095a7758be..9d6032e24e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeObjectId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeObjectId.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeString.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeString.java index e5a012775a..85902fbb03 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeString.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWith_idPropertyOfTypeString.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWriteConverter.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWriteConverter.java index 5a8f691048..bfd99b19e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWriteConverter.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWriteConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Portfolio.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Portfolio.java index e739b64385..465b237699 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Portfolio.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Portfolio.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java index 6155340002..c1a5503156 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. 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 5a5a8d6271..8867c51fc1 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-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java index 37979a30d0..909cb204e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java index fd1590203d..5134f20d13 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java index 0340a1ceb1..b11aa8bfe0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java index c0ae9a6e6d..d0a2369b76 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java index 98b654342c..39e4a3b774 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java index 7e099a3fbd..5387a12597 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java index 5163043064..18c2fd56db 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java index f0f602b737..f600407892 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java index eba8ab0e33..15dca96ab8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index a2eada0a8c..100ce97bdc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index c921ba72df..719ceb243e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java index bbbcd13a00..234fa90e1f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index c420daa62d..0bd0d49909 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java index 12997fdf89..9d9b280b46 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java index 99fadce8e5..f78c3bd78f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java index a35d32c103..519b3c748c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java index 270a45e101..33410cee61 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java index 6de3284991..aad1244fcd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java index fd0adfe6ca..b49ff97944 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java index fe9027acea..41b62aa2b6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java index d9191b9967..8a2961e620 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java index d89bdce56d..5ffb3f77fd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestEntities.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestEntities.java index b41fea370e..211b96f672 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestEntities.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestEntities.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java index 6a36b3488d..8d5017c7a3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Trade.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Trade.java index bf388a1075..912aa9e37a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Trade.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Trade.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java index dcf2f2a397..2d7d954464 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/User.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/User.java index 8dfe3f77de..8776dea1b0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/User.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/User.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Venue.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Venue.java index 709cbd25cf..58189fc52a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Venue.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/Venue.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java index 29984aa6d1..1585705c15 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index a9e3e37fee..bb477c6fa4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java index 332d866e57..12f2e744fa 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java index 48faa1e099..e898591bfd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 8c11222a37..952a2a7f32 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java index 84f07911ea..51a38ec6da 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java index 86474a4bd4..82057f9617 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java index 8fa36f773f..9096164618 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/City.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/City.java index d5d81a2035..a86b9e9a08 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/City.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/City.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java index 4623e0a1ed..9284268d2f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java index ca356281ea..89a553e590 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java index bff258a655..c5b5992b2a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Data.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Data.java index 090f5649dd..799b07d748 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Data.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Data.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DataItem.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DataItem.java index 29061e0031..bf1108733d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DataItem.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DataItem.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java index d1d14d46ee..0e73dc4344 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java index 7b719d71f5..23a630115f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java index f8e0336bf8..5a4f958d3d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java index 094b3279c3..bac532834b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java index fc20d37a3f..09b01fa5ba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java index 4601bca15d..33404d8975 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Invoice.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Invoice.java index f4ceb188a6..776bebb6b7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Invoice.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Invoice.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LikeStats.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LikeStats.java index d797320ebf..a7dd0f569b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LikeStats.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LikeStats.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LineItem.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LineItem.java index 46c0e57dcd..7c544e1732 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LineItem.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LineItem.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java index e7ea4f38d8..5e4bd6eb2c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MeterData.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MeterData.java index dc9ef359a5..436f9b34c5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MeterData.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MeterData.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java index 7dca69e055..0f15531b52 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Order.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Order.java index 33b66552f1..e77ce3b78f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Order.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Order.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java index c082a547d3..e3e70a958c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Product.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Product.java index e9bf2b46ca..bfdb033cb9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Product.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/Product.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index 12f8509873..84e35119fa 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java index d3edebeb5f..7125ba8006 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java index 18f1c39e8d..7440fbd232 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java index 18205729b8..25b231d6b6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java index 5beab8b90d..6fb94db7ef 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java index 8461994421..b3a40dcecd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java index f5eb12877a..b5b2d22ab9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java index c6b9bff7c2..cd9a9a7720 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java index 1507c83bb8..393ff4dabc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java index 3eba5bb377..d6a27fcfaf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java index 275b232c51..7cdc714b2b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index f0f1922525..d0a7f44cf5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StateStats.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StateStats.java index 502a903297..c531f03fd5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StateStats.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StateStats.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java index 6f42894515..a04afd5869 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java index bb0a0921ad..db281d0e4e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java index 9f59e429d0..cf7e960ef1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java index 0951e323a3..b6b1762a7e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java index a0e00a0b5d..3d4aecda59 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index ff7b3ab260..8a8cd8f54f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 42da6644b1..6813ac77fb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java index b16e0ede50..fe7dc08788 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java index 83c17cac33..f37bd3f8b4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java index ea88887071..5697a48cb6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index 7db97834c7..88eca20b34 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index e9dad99f4b..0fab4c3976 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java index f45858da74..4f86746f82 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java index b953ec7db3..c928e951c1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java index cdc34841d8..14263d6b61 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java index d9b52cd4ee..826e5e9340 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java index 46ebc0bcbb..f8de117a78 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java index 9b123514b1..8176c688f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index 2f8b7a6154..49cb8ef163 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 1355507928..b889bdf36e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java index 0e12ca6569..765dd0f366 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java index d08fc9d877..bd1723b8bb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java index 37a9623a86..0d0f2cd494 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java index 4284f16884..9dc7f0b943 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java index 64addf98f8..9f9b385dd6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java index a92e9da3de..cce1995069 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NumberToNumberConverterFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NumberToNumberConverterFactoryUnitTests.java index 271c43bedd..c0479cb128 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NumberToNumberConverterFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NumberToNumberConverterFactoryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java index 6dd2cf8737..f3130518cb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 3f2ed4f531..d02e37e436 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java index 671a08c3e1..9fa5e84de2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index 44f70c4227..2cc6c1542c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java index 8355c60f31..0244237d85 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java index b0deca1010..559b07b482 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index 7350b84a42..03a936c134 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java index 1240bcdaf8..7eb7e6a82d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DTests.java index 1adb751f55..e18c4a5baf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java index 1e97934d1a..47408d8446 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java index 5cff0feaba..ffb7598bc3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java index c1051d63f3..2e0dfddcb7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 8be30857e1..69053f8386 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java index b5f2d01c21..c9cdf9fc52 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index 617b46eae4..eddf555efc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 89e5081e14..8089054d25 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/PathUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/PathUnitTests.java index 6ed88814b3..66d32da110 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/PathUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/PathUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java index b236902165..0de564be78 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java index e0ffc0b893..fbd50f5895 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java index 8d94b834d4..839becd04b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/AccountPojo.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/AccountPojo.java index b5574d0f97..f17b2c573f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/AccountPojo.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/AccountPojo.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java index 27a5889498..87e76e4886 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java index c7d5bae3fe..1b0e43c38e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java index 1071d9fc7b..70c3b9767c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 72f4be2be3..5e9d6868cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java index 1eab700876..d3db39006e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java index 7f34cec888..7b993950aa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java index 619680435b..53ff50a866 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java index a08823b67f..8fde5b50c7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java index 03ee8c6964..3aa11afd14 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java index bf4fc5cfe8..e6a8364f21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java index e63a6d8ad0..d5f655a93c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java index f9ab9e94b3..685fb2f988 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java index 1fea7176eb..ce991c6766 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java index ac45be0e9d..9bf2ac676d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java index cd85adc8a6..efb0dc9b92 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java index 52075480a8..4ae87735b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java index 7d15f55139..b6e78bfb9c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomIdName.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomIdName.java index 1457eaff61..f394ccd629 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomIdName.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomIdName.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java index 26d8beaf45..140122e494 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiCollection.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiCollection.java index e35479dc4d..5d061d74e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiCollection.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiCollection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiDimArrays.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiDimArrays.java index bfad65e8f2..86b7ee350e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiDimArrays.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMultiDimArrays.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java index 1a4a9b9de1..98bcbe6c61 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoIntId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoIntId.java index 6305ef2385..d8e2b078d2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoIntId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoIntId.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoLongId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoLongId.java index 8fcfc9e5bc..6bf8b73c4c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoLongId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoLongId.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoStringId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoStringId.java index 350fe10b65..33c07fd0c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoStringId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonPojoStringId.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonSimpleList.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonSimpleList.java index 8cf3a72629..62505eff8c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonSimpleList.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonSimpleList.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java index b116b0b81e..1ecf7fe0e9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithObjectId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithObjectId.java index 3114c00440..2a5fcbf513 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithObjectId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithObjectId.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java index ca75d0cc3a..d2a6f8d9d0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java index f52acbc5b1..7a5a59815b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveListener.java index d325996811..929c9b4998 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveListener.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java index 8e0a04e269..31380caec7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java index e0aadffce2..faef0f359e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java index 9ea5267506..1cc0913aa0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java index 3dc3931a2c..34cb376f48 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java index 7c08e38584..6cd602bba7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/PersonBeforeSaveListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/PersonBeforeSaveListener.java index d5ecd765a6..39d826794c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/PersonBeforeSaveListener.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/PersonBeforeSaveListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java index bf79fdfbf4..1bf2b8a24a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java index 696249f07d..96bc28c76c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java index ebaaf7d07b..d2392dc791 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java index fb09d45477..7151c9dc46 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java index 76a6ada2cb..3b00892638 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java index c873fd45c7..e0b0d184e3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java index 99ee2faa3e..731f6cff8e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java index 3a36943ae9..cfb2dba6e1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java index 6ad1e44ec0..f734a600a8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ValueObject.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ValueObject.java index 54c3241bee..ad54dec292 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ValueObject.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ValueObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java index 71ee90638c..689f930392 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index bc12daed05..6b5f491eed 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java index 91fcb4c871..146460ea11 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index 35fc3463b7..a41b3e25fe 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java index 8c479c8121..23317f1b68 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/SubscriptionUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/SubscriptionUtils.java index 0a4142d501..5224e4a7f5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/SubscriptionUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/SubscriptionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java index 20c5f60a74..acde3583c7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java index 3ee84d5e64..2ea0e52862 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java index ecfe498d6d..25b2bce6c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java index f9f7969166..c14cfed676 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java index 566628a942..bd7d0a352d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java index 13af8b0449..c6a79ce777 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java index c4fd71da30..1a73dea770 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java index 5552214e3f..c87d7afedd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java index ee785fa0e8..a4e9cf7465 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MongoRegexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MongoRegexCreatorUnitTests.java index 16aea6e311..7c318adbe4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MongoRegexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MongoRegexCreatorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java index d0ec24062f..1285a480cc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java index baddb1a37e..b894ee9b2d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java index 14f8061af6..0a3354c7ec 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java index be6a4b6c29..d30e7b97a1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java index 732879e9a4..44baf0092f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java index 9141d8ada0..e40780cda1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java index 74babbc6fb..426ef98537 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java index cf045bded6..a56f1a7d0f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java index 1b57d2dff5..3ee7a3a16b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java index 6c7121576d..c338520b26 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java index d5b259eebc..607c5b2e30 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java index f10b457db3..92ce97149b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java index e333adf348..d4b7301c34 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java index 341be5a5e9..2a3a4a99ed 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java index dc7a97b1ac..b11bd78cc2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java index 169f0d23f9..81d34fea18 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java index 902416422c..ebd29428ad 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java index 88c6842538..59c4ef1451 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java index 7d46d4c468..86609ca8c1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java index 26eaebc6c2..e1336364f3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java index cbd5eb5c88..2495eb1f79 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 33bb5dd734..fc5fe7fc3e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 065678928c..0b18d36620 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java index 27c2ecd68a..2b666a2f57 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/Resumeable.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/Resumeable.java index db017a47aa..04fd8a6879 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/Resumeable.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/Resumeable.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java index 6d877de3a2..9f038f8f10 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java index 72c898f93a..86487164a9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 993ee6d934..f49004114c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java index 07cc231314..45defa38a6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java index ae7062dc38..0b8a74f48c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java index fd901ecf8c..9c19645343 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java index 4829004bd6..27bef5f4ab 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java index fc5195af51..9b155de4f3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java index ab47b0e2db..80447fafc7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java index ab560ef4c6..ba66f34c43 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java index 25ff2e9dd1..1298649bf7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MyId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MyId.java index 93b302e0e7..964edbf7e5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MyId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MyId.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java index 9231de1767..a0b5813b6d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java index 69dfb97990..adbe6a1eb9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonExcerpt.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonExcerpt.java index a94608f7ef..9dd0a06492 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonExcerpt.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonExcerpt.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 009a0f63d1..eb5fb07486 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests.java index 877e22ec8e..97a99eb364 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java index 51e567e353..496479c01d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index ac8b475d15..d2b9b9c6e8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummary.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummary.java index b64deeb95a..3d818a392a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummary.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummary.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryDto.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryDto.java index d0e9c03114..b257701de7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryDto.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryDto.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index e5c9574ba2..0bca9f69f3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactivePersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactivePersonRepository.java index 15ac417cbd..55402585b3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactivePersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactivePersonRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsRepository.java index d47fc21bdf..b17da40f71 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java index 4a65e5400b..14b8d291d9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java index e8017daa23..bc5da2dcd3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SampleEvaluationContextExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SampleEvaluationContextExtension.java index 1bcc5f09b8..f823c57729 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SampleEvaluationContextExtension.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SampleEvaluationContextExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java index 24e10cb062..cd213dc734 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SumAge.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SumAge.java index ce4b41d81e..0ba54e6437 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SumAge.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SumAge.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/User.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/User.java index e50b5614ba..bd0f8fbdee 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/User.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/User.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexId.java index 383dd2d383..f34ef2b2e3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexId.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java index 49b4bdd5cb..723b0acb9f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UsernameAndPassword.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UsernameAndPassword.java index e655b0e5c6..4e629be6d5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UsernameAndPassword.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UsernameAndPassword.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/VersionedPerson.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/VersionedPerson.java index 807ec91dd9..05433e36c9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/VersionedPerson.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/VersionedPerson.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java index 4dee786e62..5c3a63c331 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiPersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiPersonRepository.java index aad21fae76..501833cd81 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiPersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiPersonRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java index c0164b0efa..b72818ec65 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/RepositoryClient.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/RepositoryClient.java index bf776839c9..8016109ea3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/RepositoryClient.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/RepositoryClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragment.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragment.java index f61abb761f..fd50382fd7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragment.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragment.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragmentImpl.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragmentImpl.java index 3737b3f999..88373b74f2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragmentImpl.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonFragmentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonRepository.java index feb5a0ba23..4caca14970 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/SamplePersonRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java index d911485f03..b189938720 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java index efccbdebc1..d618703ef9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java index dafe97a2be..10f09722e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java index 201207096c..ecb42171d9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java index 3722635eff..3850973980 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java index dddfced0a1..8653727ebf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/ClassWithNestedRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/ClassWithNestedRepository.java index a971e08b52..ea47c45fba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/ClassWithNestedRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/ClassWithNestedRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java index 9a39c5f272..4d3634e181 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepository.java index b60069c2ba..b9c76b9f9e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java index 04df3d10de..805cbefbd5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepository.java index 07a7036f29..52045da4d4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepositoryImpl.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepositoryImpl.java index 2ccad27360..f0bbeed9b0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepositoryImpl.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomMongoRepositoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepository.java index 88adedf5dd..5536364b2f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryCustom.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryCustom.java index d641a4b9e4..2fa0a4ce2e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryCustom.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryCustom.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryImpl.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryImpl.java index 13788cff91..9b7fdc10ce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryImpl.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveMongoRepositoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java index 6e8626f3f5..d98c464415 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java index c68a8d2d01..baf65c2ff5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixin.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixin.java index 8c85a3f504..d37cc4fa9f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixin.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixin.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixinImpl.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixinImpl.java index 36b112197e..5a2913804f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixinImpl.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/RepositoryMixinImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. 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 89d05281a2..4d5cf58f07 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 @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java index a117b77e9e..dc69a8f786 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java index b89a1f0763..ba4fbd8274 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java index aaa464ea13..94f6e985a1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java index a39b6a063d..fce0af05af 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java index 9ad082660f..dc5e391e78 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index 986aa46f38..b40e1b3913 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java index 73acfb68f6..18d3f8f725 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. 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 692d202ac3..ba2dd25cf9 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java index 48c1e19cc6..2b9ce86991 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java index 5fb3205795..15f2c22854 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodUnitTests.java index 90d5a389b1..763781e885 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java index bea47deee1..8565bb9800 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java index a80afd7411..66396718b8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java index 102fb432f6..e77e7e77bf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 68f9e52dc1..7a3a7fb459 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StubParameterAccessor.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StubParameterAccessor.java index 788a2925ca..81382286d1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StubParameterAccessor.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StubParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java index e5ad2c718f..48f8898347 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java index c6a61584b0..ea930c0c3b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java index 78b8f152fa..9b1863dbf9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java index 86dad6bcbf..557fd6e727 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index 6d908df879..e1dd0155fe 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java index e5cb46d6ed..c714056358 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 8eee93ee0c..3c6294fbca 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 the original author or authors. + * Copyright 2010-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java index 1a5feb0ca9..760b36157c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java index ad797cb513..abfa2819d5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java index 64e34255e5..bb0d648224 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java @@ -15,7 +15,7 @@ */ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java index 0488a417a8..61474eb4c7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java index 41fedf94c9..c8b90ea22a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AfterTransactionAssertion.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AfterTransactionAssertion.java index cfd05ea171..75bf1e7695 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AfterTransactionAssertion.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AfterTransactionAssertion.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AssertErrors.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AssertErrors.java index 66b8dc1a7f..991bf43697 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AssertErrors.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/AssertErrors.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Assertions.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Assertions.java index ea0ebcaa8b..eab8addc9f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Assertions.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Assertions.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/BasicDbListBuilder.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/BasicDbListBuilder.java index 4eb5fffca0..32b8962c3f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/BasicDbListBuilder.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/BasicDbListBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java index e54e92035f..cabd2022fa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java index edc3ea5d70..8f076e9a18 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java index b209bd05e9..6060f915ac 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java index a695b3305f..7c3498004d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java index 8e0d172702..1f5bdff616 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java index 0df6c532c0..16e0141933 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoServerCondition.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoServerCondition.java index af83b4d321..a4db96e9e1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoServerCondition.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoServerCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 7691cb3070..38829da043 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersion.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersion.java index 8ec4e9f579..4936423a99 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersion.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersion.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java index bc07a8c034..229ee0f7ef 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplicaSet.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplicaSet.java index 96f24751be..d7197acc2b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplicaSet.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplicaSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index aa64c3ba78..876280e276 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. From 9bbe1f2a263d0e317711e88e71cbe4d5138fe557 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 11 Dec 2019 09:59:50 +0100 Subject: [PATCH 0016/1381] DATAMONGO-2423 - Nullability refinements for Update. Ease non null restrictions for operators that may use null values like $set. Original pull request: #815. --- .../data/mongodb/core/query/BasicUpdate.java | 9 ++++---- .../data/mongodb/core/query/Update.java | 22 +++++++++---------- .../core/MongoTemplateUpdateTests.java | 17 ++++++++++++++ 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java index 2b785ff524..00d148b890 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java @@ -19,6 +19,7 @@ import java.util.Collections; import org.bson.Document; +import org.springframework.lang.Nullable; /** * @author Thomas Risberg @@ -42,7 +43,7 @@ public BasicUpdate(Document updateObject) { } @Override - public Update set(String key, Object value) { + public Update set(String key, @Nullable Object value) { updateObject.put("$set", Collections.singletonMap(key, value)); return this; } @@ -60,7 +61,7 @@ public Update inc(String key, Number inc) { } @Override - public Update push(String key, Object value) { + public Update push(String key, @Nullable Object value) { updateObject.put("$push", Collections.singletonMap(key, value)); return this; } @@ -74,7 +75,7 @@ public Update pushAll(String key, Object[] values) { } @Override - public Update addToSet(String key, Object value) { + public Update addToSet(String key, @Nullable Object value) { updateObject.put("$addToSet", Collections.singletonMap(key, value)); return this; } @@ -86,7 +87,7 @@ public Update pop(String key, Position pos) { } @Override - public Update pull(String key, Object value) { + public Update pull(String key, @Nullable Object value) { updateObject.put("$pull", Collections.singletonMap(key, value)); return this; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index 4957bb5d50..edb79588d8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -27,7 +27,6 @@ import java.util.Set; import org.bson.Document; - import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -68,7 +67,7 @@ public enum Position { * @param key * @return */ - public static Update update(String key, Object value) { + public static Update update(String key, @Nullable Object value) { return new Update().set(key, value); } @@ -110,11 +109,12 @@ public static Update fromDocument(Document object, String... exclude) { * Update using the {@literal $set} update modifier * * @param key - * @param value - * @return + * @param value can be {@literal null}. In this case the property remains in the db with a {@literal null} value. To + * remove it use {@link #unset(String)}. + * @return this. * @see MongoDB Update operator: $set */ - public Update set(String key, Object value) { + public Update set(String key, @Nullable Object value) { addMultiFieldOperation("$set", key, value); return this; } @@ -123,12 +123,12 @@ public Update set(String key, Object value) { * Update using the {@literal $setOnInsert} update modifier * * @param key - * @param value + * @param value can be {@literal null}. * @return * @see MongoDB Update operator: * $setOnInsert */ - public Update setOnInsert(String key, Object value) { + public Update setOnInsert(String key, @Nullable Object value) { addMultiFieldOperation("$setOnInsert", key, value); return this; } @@ -175,7 +175,7 @@ public void inc(String key) { * @return * @see MongoDB Update operator: $push */ - public Update push(String key, Object value) { + public Update push(String key, @Nullable Object value) { addMultiFieldOperation("$push", key, value); return this; } @@ -238,7 +238,7 @@ public AddToSetBuilder addToSet(String key) { * @see MongoDB Update operator: * $addToSet */ - public Update addToSet(String key, Object value) { + public Update addToSet(String key, @Nullable Object value) { addMultiFieldOperation("$addToSet", key, value); return this; } @@ -264,7 +264,7 @@ public Update pop(String key, Position pos) { * @return * @see MongoDB Update operator: $pull */ - public Update pull(String key, Object value) { + public Update pull(String key, @Nullable Object value) { addMultiFieldOperation("$pull", key, value); return this; } @@ -472,7 +472,7 @@ protected void addFieldOperation(String operator, String key, Object value) { this.keysToUpdate.add(key); } - protected void addMultiFieldOperation(String operator, String key, Object value) { + protected void addMultiFieldOperation(String operator, String key, @Nullable Object value) { Assert.hasText(key, "Key/Path for update must not be null or blank."); Object existingValue = this.modifierOps.get(operator); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index 2f46f87d6d..a90371de5a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -36,6 +36,7 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -272,6 +273,22 @@ public void findAndModifyAppliesAggregationUpdateCorrectly() { } + @Test // DATAMMONGO-2423 + void nullValueShouldBePropagatedToDatabase() { + + Book currentRead = new Book(); + currentRead.id = 1; + currentRead.author = new Author("Brent", "Weeks"); + currentRead.title = "The Burning White"; + + template.save(currentRead); + + template.update(Book.class).apply(new Update().set("title", null)).first(); + + assertThat(collection(Book.class).find(new org.bson.Document("_id", currentRead.id)).first()).containsEntry("title", + null); + } + private List all(Class type) { return collection(type).find(new org.bson.Document()).into(new ArrayList<>()); } From 1393f23f3b5816039d793a2bd5515ba68152f4b9 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 11 Dec 2019 10:06:02 +0100 Subject: [PATCH 0017/1381] DATAMONGO-2423 - Polishing. Update nullability annotations and reduce visibility in tests. Original pull request: #815. --- .../mongodb/core/index/GeospatialIndex.java | 1 - .../CachingMongoPersistentProperty.java | 2 +- .../core/mapreduce/MapReduceResults.java | 1 + .../core/MongoTemplateUpdateTests.java | 32 ++++++++++++------- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java index 1e4f85cd5a..b54067d7bb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java @@ -184,7 +184,6 @@ public Document getIndexKeys() { return document; } - @Nullable public Document getIndexOptions() { Document document = new Document(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java index 662b6bee35..ddda7e8892 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java @@ -30,7 +30,7 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty private @Nullable Boolean isIdProperty; private @Nullable Boolean isAssociation; - private @Nullable boolean dbRefResolved; + private boolean dbRefResolved; private @Nullable DBRef dbref; private @Nullable String fieldName; private @Nullable Class fieldType; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java index 604528fb25..918691b3c1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java @@ -101,6 +101,7 @@ public String getOutputCollection() { return outputCollection; } + @Nullable public Document getRawResults() { return rawResults; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index a90371de5a..a98385dc40 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -48,8 +48,7 @@ * @author Christoph Strobl */ @ExtendWith(MongoServerCondition.class) -@EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") -public class MongoTemplateUpdateTests { +class MongoTemplateUpdateTests { static final String DB_NAME = "update-test"; @@ -68,7 +67,8 @@ void setUp() { } @Test // DATAMONGO-2331 - public void aggregateUpdateWithSet() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregateUpdateWithSet() { Score score1 = new Score(1, "Maya", Arrays.asList(10, 5, 10), Arrays.asList(10, 8), 0); Score score2 = new Score(2, "Ryan", Arrays.asList(5, 6, 5), Arrays.asList(8, 8), 8); @@ -92,7 +92,8 @@ public void aggregateUpdateWithSet() { } @Test // DATAMONGO-2331 - public void aggregateUpdateWithSetToValue() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregateUpdateWithSetToValue() { Book one = new Book(); one.id = 1; @@ -109,7 +110,8 @@ public void aggregateUpdateWithSetToValue() { } @Test // DATAMONGO-2331 - public void versionedAggregateUpdateWithSet() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void versionedAggregateUpdateWithSet() { Versioned source = template.insert(Versioned.class).one(new Versioned("id-1", "value-0")); @@ -123,7 +125,8 @@ public void versionedAggregateUpdateWithSet() { } @Test // DATAMONGO-2331 - public void versionedAggregateUpdateTouchingVersionProperty() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void versionedAggregateUpdateTouchingVersionProperty() { Versioned source = template.insert(Versioned.class).one(new Versioned("id-1", "value-0")); @@ -138,7 +141,8 @@ public void versionedAggregateUpdateTouchingVersionProperty() { } @Test // DATAMONGO-2331 - public void aggregateUpdateWithUnset() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregateUpdateWithUnset() { Book antelopeAntics = new Book(); antelopeAntics.id = 1; @@ -171,7 +175,8 @@ public void aggregateUpdateWithUnset() { } @Test // DATAMONGO-2331 - public void aggregateUpdateWithReplaceWith() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregateUpdateWithReplaceWith() { Book one = new Book(); one.id = 1; @@ -194,7 +199,8 @@ public void aggregateUpdateWithReplaceWith() { } @Test // DATAMONGO-2331 - public void aggregateUpdateWithReplaceWithNewObject() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregateUpdateWithReplaceWithNewObject() { Book one = new Book(); one.id = 1; @@ -217,7 +223,8 @@ public void aggregateUpdateWithReplaceWithNewObject() { } @Test // DATAMONGO-2331 - public void aggregationUpdateUpsertsCorrectly() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregationUpdateUpsertsCorrectly() { AggregationUpdate update = AggregationUpdate.update().set("title").toValue("The Burning White"); @@ -228,7 +235,8 @@ public void aggregationUpdateUpsertsCorrectly() { } @Test // DATAMONGO-2331 - public void aggregateUpdateFirstMatch() { + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") + void aggregateUpdateFirstMatch() { Book one = new Book(); one.id = 1; @@ -250,7 +258,7 @@ public void aggregateUpdateFirstMatch() { @Test // DATAMONGO-2331 @Disabled("https://jira.mongodb.org/browse/JAVA-3432") - public void findAndModifyAppliesAggregationUpdateCorrectly() { + void findAndModifyAppliesAggregationUpdateCorrectly() { Book one = new Book(); one.id = 1; From 96c4901e7ff61c3ae113f9bb4080cb5a1103db5f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 7 Jan 2020 16:13:23 +0100 Subject: [PATCH 0018/1381] DATAMONGO-2440 - Fix field target type conversion for collection values. We now preserve the collection nature of the source type when applying custom target type conversions. Prior to this change collection values had been changed to single element causing query errors in MongoDB when using $in queries. Original pull request: #817. --- .../mongodb/core/convert/QueryMapper.java | 52 ++++++++++++------- .../core/convert/QueryMapperUnitTests.java | 32 ++++++++++++ 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 81b425b9af..6013ea806a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -15,25 +15,16 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.bson.BsonValue; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; - import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Example; @@ -329,18 +320,14 @@ protected Document getMappedKeyword(Field property, Keyword keyword) { * {@link MongoPersistentProperty}. * * @param documentField the key the value will be bound to eventually - * @param value the source object to be mapped + * @param sourceValue the source object to be mapped * @return */ @Nullable @SuppressWarnings("unchecked") - protected Object getMappedValue(Field documentField, Object value) { + protected Object getMappedValue(Field documentField, Object sourceValue) { - if (documentField.getProperty() != null && documentField.getProperty().hasExplicitWriteTarget()) { - if (conversionService.canConvert(value.getClass(), documentField.getProperty().getFieldType())) { - value = conversionService.convert(value, documentField.getProperty().getFieldType()); - } - } + Object value = applyFieldTargetTypeHintToValue(documentField, sourceValue); if (documentField.isIdField() && !documentField.isAssociation()) { @@ -681,6 +668,35 @@ protected boolean isKeyword(String candidate) { return candidate.startsWith("$"); } + /** + * Convert the given field value into its desired + * {@link org.springframework.data.mongodb.core.mapping.Field#targetType() target type} before applying further + * conversions. In case of a {@link Collection} (used eg. for {@code $in} queries) the individual values will be + * converted one by one. + * + * @param documentField the field and its meta data + * @param value the actual value + * @return the potentially converted target value. + */ + private Object applyFieldTargetTypeHintToValue(Field documentField, Object value) { + + if (documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) { + return value; + } + + if (!conversionService.canConvert(value.getClass(), documentField.getProperty().getFieldType())) { + return value; + } + + if (value instanceof Collection) { + + return ((Collection) value).stream() + .map(it -> conversionService.convert(it, documentField.getProperty().getFieldType())) + .collect(Collectors.toList()); + } + return conversionService.convert(value, documentField.getProperty().getFieldType()); + } + /** * Value object to capture a query keyword representation. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index d02e37e436..88a35ca22c 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -901,6 +901,32 @@ public void leavesDistanceUntouchedWhenUsingGeoJson() { assertThat(document).containsEntry("geoJsonPoint.$near.$maxDistance", 1000.0D); } + @Test // DATAMONGO-2440 + void convertsInWithNonIdFieldAndObjectIdTypeHintCorrectly() { + + String id = new ObjectId().toHexString(); + NonIdFieldWithObjectIdTargetType source = new NonIdFieldWithObjectIdTargetType(); + + source.stringAsOid = id; + + org.bson.Document target = mapper.getMappedObject(query(where("stringAsOid").in(id)).getQueryObject(), + context.getPersistentEntity(NonIdFieldWithObjectIdTargetType.class)); + assertThat(target).isEqualTo(org.bson.Document.parse("{\"stringAsOid\": {\"$in\": [{\"$oid\": \"" + id + "\"}]}}")); + } + + @Test // DATAMONGO-2440 + void convertsInWithIdFieldAndObjectIdTypeHintCorrectly() { + + String id = new ObjectId().toHexString(); + NonIdFieldWithObjectIdTargetType source = new NonIdFieldWithObjectIdTargetType(); + + source.id = id; + + org.bson.Document target = mapper.getMappedObject(query(where("id").in(id)).getQueryObject(), + context.getPersistentEntity(NonIdFieldWithObjectIdTargetType.class)); + assertThat(target).isEqualTo(org.bson.Document.parse("{\"_id\": {\"$in\": [{\"$oid\": \"" + id + "\"}]}}")); + } + @Document public class Foo { @Id private ObjectId id; @@ -1037,4 +1063,10 @@ static class WithExplicitTargetTypes { static class WithIdPropertyContainingUnderscore { @Id String with_underscore; } + + static class NonIdFieldWithObjectIdTargetType { + + String id; + @Field(targetType = FieldType.OBJECT_ID) String stringAsOid; + } } From e2200eccf7014a28de3b35a82b83779e68a739f6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Jan 2020 15:00:36 +0100 Subject: [PATCH 0019/1381] DATAMONGO-2440 - Polishing. Iterate over List instead of using the Stream API. Reduce visibility of JUnit 5 test methods. Consolidate assertions. Original pull request: #817. --- .../mongodb/core/convert/QueryMapper.java | 16 +- .../core/convert/QueryMapperUnitTests.java | 205 +++++++++--------- 2 files changed, 112 insertions(+), 109 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 6013ea806a..ada9adec6e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -19,12 +19,12 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import org.bson.BsonValue; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; + import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Example; @@ -642,7 +642,7 @@ protected boolean isNestedKeyword(Object candidate) { return false; } - return isKeyword(keys.iterator().next().toString()); + return isKeyword(keys.iterator().next()); } /** @@ -690,10 +690,16 @@ private Object applyFieldTargetTypeHintToValue(Field documentField, Object value if (value instanceof Collection) { - return ((Collection) value).stream() - .map(it -> conversionService.convert(it, documentField.getProperty().getFieldType())) - .collect(Collectors.toList()); + Collection source = (Collection) value; + Collection converted = new ArrayList<>(source.size()); + + for (Object o : source) { + converted.add(conversionService.convert(o, documentField.getProperty().getFieldType())); + } + + return converted; } + return conversionService.convert(value, documentField.getProperty().getFieldType()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 88a35ca22c..9d116974e0 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -79,7 +79,7 @@ public class QueryMapperUnitTests { @Mock MongoDbFactory factory; @BeforeEach - public void beforeEach() { + void beforeEach() { this.context = new MongoMappingContext(); @@ -90,18 +90,18 @@ public void beforeEach() { } @Test - public void translatesIdPropertyIntoIdKey() { + void translatesIdPropertyIntoIdKey() { org.bson.Document query = new org.bson.Document("foo", "value"); MongoPersistentEntity entity = context.getRequiredPersistentEntity(Sample.class); org.bson.Document result = mapper.getMappedObject(query, entity); - assertThat(result.get("_id")).isNotNull(); - assertThat(result.get("foo")).isNull(); + assertThat(result).containsKey("_id"); + assertThat(result).doesNotContainKey("foo"); } @Test - public void convertsStringIntoObjectId() { + void convertsStringIntoObjectId() { org.bson.Document query = new org.bson.Document("_id", new ObjectId().toString()); org.bson.Document result = mapper.getMappedObject(query, context.getPersistentEntity(IdWrapper.class)); @@ -109,24 +109,24 @@ public void convertsStringIntoObjectId() { } @Test - public void handlesBigIntegerIdsCorrectly() { + void handlesBigIntegerIdsCorrectly() { org.bson.Document document = new org.bson.Document("id", new BigInteger("1")); org.bson.Document result = mapper.getMappedObject(document, context.getPersistentEntity(IdWrapper.class)); - assertThat(result.get("_id")).isEqualTo("1"); + assertThat(result).containsEntry("_id", "1"); } @Test - public void handlesObjectIdCapableBigIntegerIdsCorrectly() { + void handlesObjectIdCapableBigIntegerIdsCorrectly() { ObjectId id = new ObjectId(); org.bson.Document document = new org.bson.Document("id", new BigInteger(id.toString(), 16)); org.bson.Document result = mapper.getMappedObject(document, context.getPersistentEntity(IdWrapper.class)); - assertThat(result.get("_id")).isEqualTo(id); + assertThat(result).containsEntry("_id", id); } @Test // DATAMONGO-278 - public void translates$NeCorrectly() { + void translates$NeCorrectly() { Criteria criteria = where("foo").ne(new ObjectId().toString()); @@ -139,7 +139,7 @@ public void handlesObjectIdCapableBigIntegerIdsCorrectly() { } @Test // DATAMONGO-326 - public void handlesEnumsCorrectly() { + void handlesEnumsCorrectly() { Query query = query(where("foo").is(Enum.INSTANCE)); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), Optional.empty()); @@ -148,7 +148,7 @@ public void handlesEnumsCorrectly() { } @Test - public void handlesEnumsInNotEqualCorrectly() { + void handlesEnumsInNotEqualCorrectly() { Query query = query(where("foo").ne(Enum.INSTANCE)); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), Optional.empty()); @@ -156,12 +156,11 @@ public void handlesEnumsInNotEqualCorrectly() { assertThat(object).isInstanceOf(org.bson.Document.class); Object ne = ((org.bson.Document) object).get("$ne"); - assertThat(ne).isInstanceOf(String.class); - assertThat(ne.toString()).isEqualTo(Enum.INSTANCE.name()); + assertThat(ne).isInstanceOf(String.class).hasToString(Enum.INSTANCE.name()); } @Test - public void handlesEnumsIn$InCorrectly() { + void handlesEnumsIn$InCorrectly() { Query query = query(where("foo").in(Enum.INSTANCE)); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), Optional.empty()); @@ -174,30 +173,29 @@ public void handlesEnumsInNotEqualCorrectly() { List list = (List) in; assertThat(list).hasSize(1); - assertThat(list.get(0)).isInstanceOf(String.class); - assertThat(list.get(0).toString()).isEqualTo(Enum.INSTANCE.name()); + assertThat(list.get(0)).isInstanceOf(String.class).hasToString(Enum.INSTANCE.name()); } @Test // DATAMONGO-373 - public void handlesNativelyBuiltQueryCorrectly() { + void handlesNativelyBuiltQueryCorrectly() { DBObject query = new QueryBuilder().or(new BasicDBObject("foo", "bar")).get(); mapper.getMappedObject(new org.bson.Document(query.toMap()), Optional.empty()); } @Test // DATAMONGO-369 - public void handlesAllPropertiesIfDocument() { + void handlesAllPropertiesIfDocument() { org.bson.Document query = new org.bson.Document(); query.put("foo", new org.bson.Document("$in", Arrays.asList(1, 2))); query.put("bar", new Person()); org.bson.Document result = mapper.getMappedObject(query, Optional.empty()); - assertThat(result.get("bar")).isNotNull(); + assertThat(result).containsKey("bar"); } @Test // DATAMONGO-429 - public void transformsArraysCorrectly() { + void transformsArraysCorrectly() { Query query = new BasicQuery("{ 'tags' : { '$all' : [ 'green', 'orange']}}"); @@ -206,7 +204,7 @@ public void transformsArraysCorrectly() { } @Test - public void doesHandleNestedFieldsWithDefaultIdNames() { + void doesHandleNestedFieldsWithDefaultIdNames() { org.bson.Document document = new org.bson.Document("id", new ObjectId().toString()); document.put("nested", new org.bson.Document("id", new ObjectId().toString())); @@ -219,7 +217,7 @@ public void doesHandleNestedFieldsWithDefaultIdNames() { } @Test // DATAMONGO-493 - public void doesNotTranslateNonIdPropertiesFor$NeCriteria() { + void doesNotTranslateNonIdPropertiesFor$NeCriteria() { ObjectId accidentallyAnObjectId = new ObjectId(); @@ -231,12 +229,12 @@ public void doesHandleNestedFieldsWithDefaultIdNames() { assertThat(document.get("publishers")).isInstanceOf(org.bson.Document.class); org.bson.Document publishers = (org.bson.Document) document.get("publishers"); - assertThat(publishers.containsKey("$ne")).isTrue(); + assertThat(publishers).containsKey("$ne"); assertThat(publishers.get("$ne")).isInstanceOf(String.class); } @Test // DATAMONGO-494 - public void usesEntityMetadataInOr() { + void usesEntityMetadataInOr() { Query query = query(new Criteria().orOperator(where("foo").is("bar"))); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), @@ -248,44 +246,43 @@ public void usesEntityMetadataInOr() { assertThat(ors).hasSize(1); org.bson.Document criterias = getAsDocument(ors, 0); assertThat(criterias.keySet()).hasSize(1).doesNotContain("foo"); - assertThat(criterias.get("_id")).isNotNull(); + assertThat(criterias).containsKey("_id"); } @Test - public void translatesPropertyReferenceCorrectly() { + void translatesPropertyReferenceCorrectly() { Query query = query(where("field").is(new CustomizedField())); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class)); - assertThat(result.containsKey("foo")).isTrue(); - assertThat(result.keySet()).hasSize(1); + assertThat(result).containsKey("foo").hasSize(1); } @Test - public void translatesNestedPropertyReferenceCorrectly() { + void translatesNestedPropertyReferenceCorrectly() { Query query = query(where("field.field").is(new CustomizedField())); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class)); - assertThat(result.containsKey("foo.foo")).isTrue(); + assertThat(result).containsKey("foo.foo"); assertThat(result.keySet()).hasSize(1); } @Test - public void returnsOriginalKeyIfNoPropertyReference() { + void returnsOriginalKeyIfNoPropertyReference() { Query query = query(where("bar").is(new CustomizedField())); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class)); - assertThat(result.containsKey("bar")).isTrue(); + assertThat(result).containsKey("bar"); assertThat(result.keySet()).hasSize(1); } @Test - public void convertsAssociationCorrectly() { + void convertsAssociationCorrectly() { Reference reference = new Reference(); reference.id = 5L; @@ -300,7 +297,7 @@ public void convertsAssociationCorrectly() { } @Test - public void convertsNestedAssociationCorrectly() { + void convertsNestedAssociationCorrectly() { Reference reference = new Reference(); reference.id = 5L; @@ -315,7 +312,7 @@ public void convertsNestedAssociationCorrectly() { } @Test - public void convertsInKeywordCorrectly() { + void convertsInKeywordCorrectly() { Reference first = new Reference(); first.id = 5L; @@ -336,7 +333,7 @@ public void convertsInKeywordCorrectly() { } @Test // DATAMONGO-570 - public void correctlyConvertsNullReference() { + void correctlyConvertsNullReference() { Query query = query(where("reference").is(null)); org.bson.Document object = mapper.getMappedObject(query.getQueryObject(), @@ -346,20 +343,20 @@ public void correctlyConvertsNullReference() { } @Test // DATAMONGO-629 - public void doesNotMapIdIfNoEntityMetadataAvailable() { + void doesNotMapIdIfNoEntityMetadataAvailable() { String id = new ObjectId().toString(); Query query = query(where("id").is(id)); org.bson.Document object = mapper.getMappedObject(query.getQueryObject(), Optional.empty()); - assertThat(object.containsKey("id")).isTrue(); - assertThat(object.get("id")).isEqualTo(id); - assertThat(object.containsKey("_id")).isFalse(); + assertThat(object).containsKey("id"); + assertThat(object).containsEntry("id", id); + assertThat(object).doesNotContainKey("_id"); } @Test // DATAMONGO-677 - public void handleMapWithDBRefCorrectly() { + void handleMapWithDBRefCorrectly() { org.bson.Document mapDocument = new org.bson.Document(); mapDocument.put("test", new com.mongodb.DBRef("test", "test")); @@ -368,24 +365,24 @@ public void handleMapWithDBRefCorrectly() { org.bson.Document mapped = mapper.getMappedObject(document, context.getPersistentEntity(WithMapDBRef.class)); - assertThat(mapped.containsKey("mapWithDBRef")).isTrue(); + assertThat(mapped).containsKey("mapWithDBRef"); assertThat(mapped.get("mapWithDBRef")).isInstanceOf(org.bson.Document.class); - assertThat(((org.bson.Document) mapped.get("mapWithDBRef")).containsKey("test")).isTrue(); + assertThat(((org.bson.Document) mapped.get("mapWithDBRef"))).containsKey("test"); assertThat(((org.bson.Document) mapped.get("mapWithDBRef")).get("test")).isInstanceOf(com.mongodb.DBRef.class); } @Test - public void convertsUnderscoreIdValueWithoutMetadata() { + void convertsUnderscoreIdValueWithoutMetadata() { org.bson.Document document = new org.bson.Document().append("_id", new ObjectId().toString()); org.bson.Document mapped = mapper.getMappedObject(document, Optional.empty()); - assertThat(mapped.containsKey("_id")).isTrue(); + assertThat(mapped).containsKey("_id"); assertThat(mapped.get("_id")).isInstanceOf(ObjectId.class); } @Test // DATAMONGO-705 - public void convertsDBRefWithExistsQuery() { + void convertsDBRefWithExistsQuery() { Query query = query(where("reference").exists(false)); @@ -393,12 +390,12 @@ public void convertsDBRefWithExistsQuery() { org.bson.Document mappedObject = mapper.getMappedObject(query.getQueryObject(), entity); org.bson.Document reference = getAsDocument(mappedObject, "reference"); - assertThat(reference.containsKey("$exists")).isTrue(); - assertThat(reference.get("$exists")).isEqualTo(false); + assertThat(reference).containsKey("$exists"); + assertThat(reference).containsEntry("$exists", false); } @Test // DATAMONGO-706 - public void convertsNestedDBRefsCorrectly() { + void convertsNestedDBRefsCorrectly() { Reference reference = new Reference(); reference.id = 5L; @@ -408,7 +405,7 @@ public void convertsNestedDBRefsCorrectly() { BasicMongoPersistentEntity entity = context.getRequiredPersistentEntity(WithDBRef.class); org.bson.Document mappedObject = mapper.getMappedObject(query.getQueryObject(), entity); - assertThat(mappedObject.get("someString")).isEqualTo("foo"); + assertThat(mappedObject).containsEntry("someString", "foo"); List andClause = getAsDBList(mappedObject, "$and"); assertThat(andClause).hasSize(1); @@ -419,29 +416,29 @@ public void convertsNestedDBRefsCorrectly() { } @Test // DATAMONGO-752 - public void mapsSimpleValuesStartingWith$Correctly() { + void mapsSimpleValuesStartingWith$Correctly() { Query query = query(where("myvalue").is("$334")); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), Optional.empty()); assertThat(result.keySet()).hasSize(1); - assertThat(result.get("myvalue")).isEqualTo("$334"); + assertThat(result).containsEntry("myvalue", "$334"); } @Test // DATAMONGO-752 - public void mapsKeywordAsSimpleValuesCorrectly() { + void mapsKeywordAsSimpleValuesCorrectly() { Query query = query(where("myvalue").is("$center")); org.bson.Document result = mapper.getMappedObject(query.getQueryObject(), Optional.empty()); assertThat(result.keySet()).hasSize(1); - assertThat(result.get("myvalue")).isEqualTo("$center"); + assertThat(result).containsEntry("myvalue", "$center"); } @Test // DATAMONGO-805 - public void shouldExcludeDBRefAssociation() { + void shouldExcludeDBRefAssociation() { Query query = query(where("someString").is("foo")); query.fields().exclude("reference"); @@ -450,12 +447,12 @@ public void shouldExcludeDBRefAssociation() { org.bson.Document queryResult = mapper.getMappedObject(query.getQueryObject(), entity); org.bson.Document fieldsResult = mapper.getMappedObject(query.getFieldsObject(), entity); - assertThat(queryResult.get("someString")).isEqualTo("foo"); - assertThat(fieldsResult.get("reference")).isEqualTo(0); + assertThat(queryResult).containsEntry("someString", "foo"); + assertThat(fieldsResult).containsEntry("reference", 0); } @Test // DATAMONGO-686 - public void queryMapperShouldNotChangeStateInGivenQueryObjectWhenIdConstrainedByInList() { + void queryMapperShouldNotChangeStateInGivenQueryObjectWhenIdConstrainedByInList() { BasicMongoPersistentEntity persistentEntity = context.getRequiredPersistentEntity(Sample.class); String idPropertyName = persistentEntity.getIdProperty().getName(); @@ -469,7 +466,7 @@ public void queryMapperShouldNotChangeStateInGivenQueryObjectWhenIdConstrainedBy } @Test // DATAMONGO-821 - public void queryMapperShouldNotTryToMapDBRefListPropertyIfNestedInsideDocumentWithinDocument() { + void queryMapperShouldNotTryToMapDBRefListPropertyIfNestedInsideDocumentWithinDocument() { org.bson.Document queryObject = query( where("referenceList").is(new org.bson.Document("$nested", new org.bson.Document("$keys", 0L)))) @@ -484,7 +481,7 @@ public void queryMapperShouldNotTryToMapDBRefListPropertyIfNestedInsideDocumentW } @Test // DATAMONGO-821 - public void queryMapperShouldNotTryToMapDBRefPropertyIfNestedInsideDocumentWithinDocument() { + void queryMapperShouldNotTryToMapDBRefPropertyIfNestedInsideDocumentWithinDocument() { org.bson.Document queryObject = query( where("reference").is(new org.bson.Document("$nested", new org.bson.Document("$keys", 0L)))).getQueryObject(); @@ -497,7 +494,7 @@ public void queryMapperShouldNotTryToMapDBRefPropertyIfNestedInsideDocumentWithi } @Test // DATAMONGO-821 - public void queryMapperShouldMapDBRefPropertyIfNestedInDocument() { + void queryMapperShouldMapDBRefPropertyIfNestedInDocument() { Reference sample = new Reference(); sample.id = 321L; @@ -513,7 +510,7 @@ public void queryMapperShouldMapDBRefPropertyIfNestedInDocument() { } @Test // DATAMONGO-773 - public void queryMapperShouldBeAbleToProcessQueriesThatIncludeDbRefFields() { + void queryMapperShouldBeAbleToProcessQueriesThatIncludeDbRefFields() { BasicMongoPersistentEntity persistentEntity = context.getRequiredPersistentEntity(WithDBRef.class); @@ -525,7 +522,7 @@ public void queryMapperShouldBeAbleToProcessQueriesThatIncludeDbRefFields() { } @Test // DATAMONGO-893 - public void classInformationShouldNotBePresentInDocumentUsedInFinderMethods() { + void classInformationShouldNotBePresentInDocumentUsedInFinderMethods() { EmbeddedClass embedded = new EmbeddedClass(); embedded.id = "1"; @@ -539,7 +536,7 @@ public void classInformationShouldNotBePresentInDocumentUsedInFinderMethods() { } @Test // DATAMONGO-1406 - public void shouldMapQueryForNestedCustomizedPropertiesUsingConfiguredFieldNames() { + void shouldMapQueryForNestedCustomizedPropertiesUsingConfiguredFieldNames() { EmbeddedClass embeddedClass = new EmbeddedClass(); embeddedClass.customizedField = "hello"; @@ -558,7 +555,7 @@ public void shouldMapQueryForNestedCustomizedPropertiesUsingConfiguredFieldNames } @Test // DATAMONGO-647 - public void customizedFieldNameShouldBeMappedCorrectlyWhenApplyingSort() { + void customizedFieldNameShouldBeMappedCorrectlyWhenApplyingSort() { Query query = query(where("field").is("bar")).with(Sort.by(Direction.DESC, "field")); org.bson.Document document = mapper.getMappedObject(query.getSortObject(), @@ -567,7 +564,7 @@ public void customizedFieldNameShouldBeMappedCorrectlyWhenApplyingSort() { } @Test // DATAMONGO-973 - public void getMappedFieldsAppendsTextScoreFieldProperlyCorrectlyWhenNotPresent() { + void getMappedFieldsAppendsTextScoreFieldProperlyCorrectlyWhenNotPresent() { Query query = new Query(); @@ -579,7 +576,7 @@ public void getMappedFieldsAppendsTextScoreFieldProperlyCorrectlyWhenNotPresent( } @Test // DATAMONGO-973 - public void getMappedFieldsReplacesTextScoreFieldProperlyCorrectlyWhenPresent() { + void getMappedFieldsReplacesTextScoreFieldProperlyCorrectlyWhenPresent() { Query query = new Query(); query.fields().include("textScore"); @@ -592,7 +589,7 @@ public void getMappedFieldsReplacesTextScoreFieldProperlyCorrectlyWhenPresent() } @Test // DATAMONGO-973 - public void getMappedSortAppendsTextScoreProperlyWhenSortedByScore() { + void getMappedSortAppendsTextScoreProperlyWhenSortedByScore() { Query query = new Query().with(Sort.by("textScore")); @@ -604,7 +601,7 @@ public void getMappedSortAppendsTextScoreProperlyWhenSortedByScore() { } @Test // DATAMONGO-973 - public void getMappedSortIgnoresTextScoreWhenNotSortedByScore() { + void getMappedSortIgnoresTextScoreWhenNotSortedByScore() { Query query = new Query().with(Sort.by("id")); @@ -615,20 +612,20 @@ public void getMappedSortIgnoresTextScoreWhenNotSortedByScore() { } @Test // DATAMONGO-1070, DATAMONGO-1798 - public void mapsIdReferenceToDBRefCorrectly() { + void mapsIdReferenceToDBRefCorrectly() { ObjectId id = new ObjectId(); org.bson.Document query = new org.bson.Document("reference.id", new com.mongodb.DBRef("reference", id)); org.bson.Document result = mapper.getMappedObject(query, context.getPersistentEntity(WithDBRef.class)); - assertThat(result.containsKey("reference")).isTrue(); + assertThat(result).containsKey("reference"); com.mongodb.DBRef reference = getTypedValue(result, "reference", com.mongodb.DBRef.class); assertThat(reference.getId()).isInstanceOf(ObjectId.class); } @Test // DATAMONGO-1050 - public void shouldUseExplicitlySetFieldnameForIdPropertyCandidates() { + void shouldUseExplicitlySetFieldnameForIdPropertyCandidates() { Query query = query(where("nested.id").is("bar")); @@ -639,7 +636,7 @@ public void shouldUseExplicitlySetFieldnameForIdPropertyCandidates() { } @Test // DATAMONGO-1050 - public void shouldUseExplicitlySetFieldnameForIdPropertyCandidatesUsedInSortClause() { + void shouldUseExplicitlySetFieldnameForIdPropertyCandidatesUsedInSortClause() { Query query = new Query().with(Sort.by("nested.id")); @@ -650,7 +647,7 @@ public void shouldUseExplicitlySetFieldnameForIdPropertyCandidatesUsedInSortClau } @Test // DATAMONGO-1135 - public void nearShouldUseGeoJsonRepresentationOnUnmappedProperty() { + void nearShouldUseGeoJsonRepresentationOnUnmappedProperty() { Query query = query(where("foo").near(new GeoJsonPoint(100, 50))); @@ -663,7 +660,7 @@ public void nearShouldUseGeoJsonRepresentationOnUnmappedProperty() { } @Test // DATAMONGO-1135 - public void nearShouldUseGeoJsonRepresentationWhenMappingToGoJsonType() { + void nearShouldUseGeoJsonRepresentationWhenMappingToGoJsonType() { Query query = query(where("geoJsonPoint").near(new GeoJsonPoint(100, 50))); @@ -674,7 +671,7 @@ public void nearShouldUseGeoJsonRepresentationWhenMappingToGoJsonType() { } @Test // DATAMONGO-1135 - public void nearSphereShouldUseGeoJsonRepresentationWhenMappingToGoJsonType() { + void nearSphereShouldUseGeoJsonRepresentationWhenMappingToGoJsonType() { Query query = query(where("geoJsonPoint").nearSphere(new GeoJsonPoint(100, 50))); @@ -685,7 +682,7 @@ public void nearSphereShouldUseGeoJsonRepresentationWhenMappingToGoJsonType() { } @Test // DATAMONGO-1135 - public void shouldMapNameCorrectlyForGeoJsonType() { + void shouldMapNameCorrectlyForGeoJsonType() { Query query = query(where("namedGeoJsonPoint").nearSphere(new GeoJsonPoint(100, 50))); @@ -696,7 +693,7 @@ public void shouldMapNameCorrectlyForGeoJsonType() { } @Test // DATAMONGO-1135 - public void withinShouldUseGeoJsonPolygonWhenMappingPolygonOn2DSphereIndex() { + void withinShouldUseGeoJsonPolygonWhenMappingPolygonOn2DSphereIndex() { Query query = query(where("geoJsonPoint") .within(new GeoJsonPolygon(new Point(0, 0), new Point(100, 100), new Point(100, 0), new Point(0, 0)))); @@ -708,7 +705,7 @@ public void withinShouldUseGeoJsonPolygonWhenMappingPolygonOn2DSphereIndex() { } @Test // DATAMONGO-1134 - public void intersectsShouldUseGeoJsonRepresentationCorrectly() { + void intersectsShouldUseGeoJsonRepresentationCorrectly() { Query query = query(where("geoJsonPoint") .intersects(new GeoJsonPolygon(new Point(0, 0), new Point(100, 100), new Point(100, 0), new Point(0, 0)))); @@ -721,29 +718,29 @@ public void intersectsShouldUseGeoJsonRepresentationCorrectly() { } @Test // DATAMONGO-1269 - public void mappingShouldRetainNumericMapKey() { + void mappingShouldRetainNumericMapKey() { Query query = query(where("map.1.stringProperty").is("ba'alzamon")); org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(EntityWithComplexValueTypeMap.class)); - assertThat(document.containsKey("map.1.stringProperty")).isTrue(); + assertThat(document).containsKey("map.1.stringProperty"); } @Test // DATAMONGO-1269 - public void mappingShouldRetainNumericPositionInList() { + void mappingShouldRetainNumericPositionInList() { Query query = query(where("list.1.stringProperty").is("ba'alzamon")); org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(EntityWithComplexValueTypeList.class)); - assertThat(document.containsKey("list.1.stringProperty")).isTrue(); + assertThat(document).containsKey("list.1.stringProperty"); } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectly() { + void exampleShouldBeMappedCorrectly() { Foo probe = new Foo(); probe.embedded = new EmbeddedClass(); @@ -757,7 +754,7 @@ public void exampleShouldBeMappedCorrectly() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() { + void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() { ClassWithGeoTypes probe = new ClassWithGeoTypes(); probe.legacyPoint = new Point(10D, 20D); @@ -767,12 +764,12 @@ public void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() { org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class)); - assertThat(document.get("legacyPoint.x")).isEqualTo(10D); - assertThat(document.get("legacyPoint.y")).isEqualTo(20D); + assertThat(document).containsEntry("legacyPoint.x", 10D); + assertThat(document).containsEntry("legacyPoint.y", 20D); } @Test // DATAMONGO-1988 - public void mapsStringObjectIdRepresentationToObjectIdWhenReferencingIdProperty() { + void mapsStringObjectIdRepresentationToObjectIdWhenReferencingIdProperty() { Query query = query(where("sample.foo").is(new ObjectId().toHexString())); org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), @@ -782,7 +779,7 @@ public void mapsStringObjectIdRepresentationToObjectIdWhenReferencingIdProperty( } @Test // DATAMONGO-1988 - public void matchesExactFieldNameToIdProperty() { + void matchesExactFieldNameToIdProperty() { Query query = query(where("sample.iid").is(new ObjectId().toHexString())); org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), @@ -792,7 +789,7 @@ public void matchesExactFieldNameToIdProperty() { } @Test // DATAMONGO-1988 - public void leavesNonObjectIdStringIdRepresentationUntouchedWhenReferencingIdProperty() { + void leavesNonObjectIdStringIdRepresentationUntouchedWhenReferencingIdProperty() { Query query = query(where("sample.foo").is("id-1")); org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), @@ -802,7 +799,7 @@ public void leavesNonObjectIdStringIdRepresentationUntouchedWhenReferencingIdPro } @Test // DATAMONGO-2168 - public void getMappedObjectShouldNotMapTypeHint() { + void getMappedObjectShouldNotMapTypeHint() { converter.setTypeMapper(new DefaultMongoTypeMapper("className")); @@ -813,7 +810,7 @@ public void getMappedObjectShouldNotMapTypeHint() { } @Test // DATAMONGO-2168 - public void getMappedObjectShouldIgnorePathsLeadingToJavaLangClassProperties/* like Class#getName() */() { + void getMappedObjectShouldIgnorePathsLeadingToJavaLangClassProperties/* like Class#getName() */() { org.bson.Document update = new org.bson.Document("className", "foo"); org.bson.Document mappedObject = mapper.getMappedObject(update, context.getPersistentEntity(UserEntity.class)); @@ -822,7 +819,7 @@ public void getMappedObjectShouldNotMapTypeHint() { } @Test // DATAMONGO-2193 - public void shouldNotConvertHexStringToObjectIdForRenamedNestedIdField() { + void shouldNotConvertHexStringToObjectIdForRenamedNestedIdField() { String idHex = new ObjectId().toHexString(); Query query = new Query(where("nested.id").is(idHex)); @@ -834,7 +831,7 @@ public void shouldNotConvertHexStringToObjectIdForRenamedNestedIdField() { } @Test // DATAMONGO-2221 - public void shouldNotConvertHexStringToObjectIdForRenamedDeeplyNestedIdField() { + void shouldNotConvertHexStringToObjectIdForRenamedDeeplyNestedIdField() { String idHex = new ObjectId().toHexString(); Query query = new Query(where("nested.deeplyNested.id").is(idHex)); @@ -846,7 +843,7 @@ public void shouldNotConvertHexStringToObjectIdForRenamedDeeplyNestedIdField() { } @Test // DATAMONGO-2221 - public void shouldNotConvertHexStringToObjectIdForUnresolvablePath() { + void shouldNotConvertHexStringToObjectIdForUnresolvablePath() { String idHex = new ObjectId().toHexString(); Query query = new Query(where("nested.unresolvablePath.id").is(idHex)); @@ -858,7 +855,7 @@ public void shouldNotConvertHexStringToObjectIdForUnresolvablePath() { } @Test // DATAMONGO-1849 - public void shouldConvertPropertyWithExplicitTargetType() { + void shouldConvertPropertyWithExplicitTargetType() { String script = "if (a > b) a else b"; Query query = new Query(where("script").is(script)); @@ -870,7 +867,7 @@ public void shouldConvertPropertyWithExplicitTargetType() { } @Test // DATAMONGO-1849 - public void shouldConvertCollectionPropertyWithExplicitTargetType() { + void shouldConvertCollectionPropertyWithExplicitTargetType() { String script = "if (a > b) a else b"; Query query = new Query(where("scripts").is(script)); @@ -882,7 +879,7 @@ public void shouldConvertCollectionPropertyWithExplicitTargetType() { } @Test // DATAMONGO-2339 - public void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() { + void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() { org.bson.Document target = mapper.getMappedObject(new org.bson.Document("with_underscore", "id-1"), context.getPersistentEntity(WithIdPropertyContainingUnderscore.class)); @@ -891,7 +888,7 @@ public void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() { } @Test // DATAMONGO-2394 - public void leavesDistanceUntouchedWhenUsingGeoJson() { + void leavesDistanceUntouchedWhenUsingGeoJson() { Query query = query(where("geoJsonPoint").near(new GeoJsonPoint(27.987901, 86.9165379)).maxDistance(1000)); @@ -928,17 +925,17 @@ void convertsInWithIdFieldAndObjectIdTypeHintCorrectly() { } @Document - public class Foo { + class Foo { @Id private ObjectId id; EmbeddedClass embedded; @Field("my_items") List listOfItems; } - public class EmbeddedClass { - public String id; + class EmbeddedClass { + String id; - @Field("fancy_custom_name") public String customizedField; + @Field("fancy_custom_name") String customizedField; } class IdWrapper { From 4a45928aee35c673fb48c57bdc70c5910ab9e4f6 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Jan 2020 08:41:27 +0100 Subject: [PATCH 0020/1381] DATAMONGO-2442 - Fix thenValueOf in $cond builder. We now create a field reference when calling the builder instead of using the value as is. Original pull request: #818. --- .../core/aggregation/ConditionalOperators.java | 2 +- .../core/aggregation/AggregationUnitTests.java | 5 ++--- .../aggregation/CondExpressionUnitTests.java | 16 ++++++++-------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java index 07bfebd701..16b8efe79c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java @@ -207,7 +207,7 @@ public OtherwiseBuilder thenValueOf(AggregationExpression expression) { public OtherwiseBuilder thenValueOf(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); - return createThenBuilder().then(fieldReference); + return createThenBuilder().thenValueOf(fieldReference); } private ThenBuilder createThenBuilder() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java index 12f2e744fa..43a9cc668e 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java @@ -27,7 +27,6 @@ import org.bson.Document; import org.junit.Test; - import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond; import org.springframework.data.mongodb.core.query.Criteria; @@ -438,14 +437,14 @@ public void shouldRenderProjectionConditionalWithCriteriaCorrectly() { assertThat(getAsDocument(project, "color")).containsEntry("$cond", expectedCondition); } - @Test // DATAMONGO-861 + @Test // DATAMONGO-861, DATAMONGO-2242 public void referencingProjectionAliasesShouldRenderProjectionConditionalWithFieldReferenceCorrectly() { Document agg = Aggregation.newAggregation(// project().and("color").as("chroma"), project().and("luminosity") // .applyCondition(ConditionalOperators // .when("chroma") // - .thenValueOf("bright") // + .then("bright") // .otherwise("dark"))) // .toDocument("foo", Aggregation.DEFAULT_CONTEXT); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java index 9284268d2f..f206e683a1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java @@ -54,7 +54,7 @@ public void builderRejectsBuilderAsThenValue() { () -> newBuilder().when("isYellow").then(newBuilder().when("field").then("then-value")).otherwise("otherwise")); } - @Test // DATAMONGO-861, DATAMONGO-1542 + @Test // DATAMONGO-861, DATAMONGO-1542, DATAMONGO-2242 public void simpleBuilderShouldRenderCorrectly() { Cond operator = ConditionalOperators.when("isYellow").thenValueOf("bright").otherwise("dark"); @@ -62,13 +62,13 @@ public void simpleBuilderShouldRenderCorrectly() { Document expectedCondition = new Document() // .append("if", "$isYellow") // - .append("then", "bright") // + .append("then", "$bright") // .append("else", "dark"); assertThat(document).containsEntry("$cond", expectedCondition); } - @Test // DATAMONGO-861, DATAMONGO-1542 + @Test // DATAMONGO-861, DATAMONGO-1542, DATAMONGO-2242 public void simpleCriteriaShouldRenderCorrectly() { Cond operator = ConditionalOperators.when(Criteria.where("luminosity").gte(100)).thenValueOf("bright") @@ -77,13 +77,13 @@ public void simpleCriteriaShouldRenderCorrectly() { Document expectedCondition = new Document() // .append("if", new Document("$gte", Arrays. asList("$luminosity", 100))) // - .append("then", "bright") // + .append("then", "$bright") // .append("else", "dark"); assertThat(document).containsEntry("$cond", expectedCondition); } - @Test // DATAMONGO-861 + @Test // DATAMONGO-861, DATAMONGO-2242 public void andCriteriaShouldRenderCorrectly() { Cond operator = ConditionalOperators.when(Criteria.where("luminosity").gte(100) // @@ -99,13 +99,13 @@ public void andCriteriaShouldRenderCorrectly() { Document expectedCondition = new Document() // .append("if", Arrays. asList(luminosity, new Document("$and", Arrays.asList(hue, saturation)))) // - .append("then", "bright") // + .append("then", "$bright") // .append("else", "$dark-field"); assertThat(document).containsEntry("$cond", expectedCondition); } - @Test // DATAMONGO-861, DATAMONGO-1542 + @Test // DATAMONGO-861, DATAMONGO-1542, DATAMONGO-2242 public void twoArgsCriteriaShouldRenderCorrectly() { Criteria criteria = Criteria.where("luminosity").gte(100) // @@ -119,7 +119,7 @@ public void twoArgsCriteriaShouldRenderCorrectly() { Document expectedCondition = new Document() // .append("if", Arrays.asList(gte, is)) // - .append("then", "bright") // + .append("then", "$bright") // .append("else", "dark"); assertThat(document).containsEntry("$cond", expectedCondition); From b4222c5646c602ec055e6a550ab8d7f2e962d860 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Jan 2020 08:43:10 +0100 Subject: [PATCH 0021/1381] DATAMONGO-2442 - Polishing. Transition touched test classes to JUnit Jupiter. Original pull request: #818. --- .../data/mongodb/core/aggregation/AggregationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/CondExpressionUnitTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java index 43a9cc668e..c8e08c0b85 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java @@ -26,7 +26,7 @@ import java.util.List; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond; import org.springframework.data.mongodb.core.query.Criteria; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java index f206e683a1..740560e3fd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java @@ -21,7 +21,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond; import org.springframework.data.mongodb.core.query.Criteria; From 61bd56dd746767e2c759f94f66336bf25ef87ca6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Jan 2020 15:11:43 +0100 Subject: [PATCH 0022/1381] DATAMONGO-2442 - Polishing. Reduce visibility of test methods for JUnit 5 tests. Original pull request: #818. --- .../aggregation/AggregationUnitTests.java | 76 +++++++++---------- .../aggregation/CondExpressionUnitTests.java | 18 ++--- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java index c8e08c0b85..e51932abe7 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java @@ -42,27 +42,27 @@ public class AggregationUnitTests { @Test - public void rejectsNullAggregationOperation() { + void rejectsNullAggregationOperation() { assertThatIllegalArgumentException().isThrownBy(() -> newAggregation((AggregationOperation[]) null)); } @Test - public void rejectsNullTypedAggregationOperation() { + void rejectsNullTypedAggregationOperation() { assertThatIllegalArgumentException().isThrownBy(() -> newAggregation(String.class, (AggregationOperation[]) null)); } @Test - public void rejectsNoAggregationOperation() { + void rejectsNoAggregationOperation() { assertThatIllegalArgumentException().isThrownBy(() -> newAggregation(new AggregationOperation[0])); } @Test - public void rejectsNoTypedAggregationOperation() { + void rejectsNoTypedAggregationOperation() { assertThatIllegalArgumentException().isThrownBy(() -> newAggregation(String.class, new AggregationOperation[0])); } @Test // DATAMONGO-753 - public void checkForCorrectFieldScopeTransfer() { + void checkForCorrectFieldScopeTransfer() { assertThatIllegalArgumentException().isThrownBy(() -> { newAggregation( // @@ -74,7 +74,7 @@ public void checkForCorrectFieldScopeTransfer() { } @Test // DATAMONGO-753 - public void unwindOperationShouldNotChangeAvailableFields() { + void unwindOperationShouldNotChangeAvailableFields() { newAggregation( // project("a", "b"), // @@ -84,7 +84,7 @@ public void unwindOperationShouldNotChangeAvailableFields() { } @Test // DATAMONGO-1391 - public void unwindOperationWithIndexShouldPreserveFields() { + void unwindOperationWithIndexShouldPreserveFields() { newAggregation( // project("a", "b"), // @@ -94,7 +94,7 @@ public void unwindOperationWithIndexShouldPreserveFields() { } @Test // DATAMONGO-1391 - public void unwindOperationWithIndexShouldAddIndexField() { + void unwindOperationWithIndexShouldAddIndexField() { newAggregation( // project("a", "b"), // @@ -104,7 +104,7 @@ public void unwindOperationWithIndexShouldAddIndexField() { } @Test // DATAMONGO-1391 - public void fullUnwindOperationShouldBuildCorrectClause() { + void fullUnwindOperationShouldBuildCorrectClause() { Document agg = newAggregation( // unwind("a", "x", true)).toDocument("foo", Aggregation.DEFAULT_CONTEXT); @@ -117,7 +117,7 @@ public void fullUnwindOperationShouldBuildCorrectClause() { } @Test // DATAMONGO-1391 - public void unwindOperationWithPreserveNullShouldBuildCorrectClause() { + void unwindOperationWithPreserveNullShouldBuildCorrectClause() { Document agg = newAggregation( // unwind("a", true)).toDocument("foo", Aggregation.DEFAULT_CONTEXT); @@ -130,7 +130,7 @@ public void unwindOperationWithPreserveNullShouldBuildCorrectClause() { } @Test // DATAMONGO-1550 - public void replaceRootOperationShouldBuildCorrectClause() { + void replaceRootOperationShouldBuildCorrectClause() { Document agg = newAggregation( // replaceRoot().withDocument().andValue("value").as("field")) // @@ -142,7 +142,7 @@ public void replaceRootOperationShouldBuildCorrectClause() { } @Test // DATAMONGO-753 - public void matchOperationShouldNotChangeAvailableFields() { + void matchOperationShouldNotChangeAvailableFields() { newAggregation( // project("a", "b"), // @@ -152,7 +152,7 @@ public void matchOperationShouldNotChangeAvailableFields() { } @Test // DATAMONGO-788 - public void referencesToGroupIdsShouldBeRenderedAsReferences() { + void referencesToGroupIdsShouldBeRenderedAsReferences() { Document agg = newAggregation( // project("a"), // @@ -168,7 +168,7 @@ public void referencesToGroupIdsShouldBeRenderedAsReferences() { } @Test // DATAMONGO-791 - public void allowAggregationOperationsToBePassedAsIterable() { + void allowAggregationOperationsToBePassedAsIterable() { List ops = new ArrayList(); ops.add(project("a")); @@ -185,7 +185,7 @@ public void allowAggregationOperationsToBePassedAsIterable() { } @Test // DATAMONGO-791 - public void allowTypedAggregationOperationsToBePassedAsIterable() { + void allowTypedAggregationOperationsToBePassedAsIterable() { List ops = new ArrayList<>(); ops.add(project("a")); @@ -202,7 +202,7 @@ public void allowTypedAggregationOperationsToBePassedAsIterable() { } @Test // DATAMONGO-838 - public void expressionBasedFieldsShouldBeReferencableInFollowingOperations() { + void expressionBasedFieldsShouldBeReferencableInFollowingOperations() { Document agg = newAggregation( // project("a").andExpression("b+c").as("foo"), // @@ -216,7 +216,7 @@ public void expressionBasedFieldsShouldBeReferencableInFollowingOperations() { } @Test // DATAMONGO-908 - public void shouldSupportReferingToNestedPropertiesInGroupOperation() { + void shouldSupportReferingToNestedPropertiesInGroupOperation() { Document agg = newAggregation( // project("cmsParameterId", "rules"), // @@ -234,7 +234,7 @@ public void shouldSupportReferingToNestedPropertiesInGroupOperation() { } @Test // DATAMONGO-1585 - public void shouldSupportSortingBySyntheticAndExposedGroupFields() { + void shouldSupportSortingBySyntheticAndExposedGroupFields() { Document agg = newAggregation( // group("cmsParameterId").addToSet("title").as("titles"), // @@ -250,7 +250,7 @@ public void shouldSupportSortingBySyntheticAndExposedGroupFields() { } @Test // DATAMONGO-1585 - public void shouldSupportSortingByProjectedFields() { + void shouldSupportSortingByProjectedFields() { Document agg = newAggregation( // project("cmsParameterId") // @@ -269,7 +269,7 @@ public void shouldSupportSortingByProjectedFields() { } @Test // DATAMONGO-924 - public void referencingProjectionAliasesFromPreviousStepShouldReferToTheSameFieldTarget() { + void referencingProjectionAliasesFromPreviousStepShouldReferToTheSameFieldTarget() { Document agg = newAggregation( // project().and("foo.bar").as("ba") // @@ -284,7 +284,7 @@ public void referencingProjectionAliasesFromPreviousStepShouldReferToTheSameFiel } @Test // DATAMONGO-960 - public void shouldRenderAggregationWithDefaultOptionsCorrectly() { + void shouldRenderAggregationWithDefaultOptionsCorrectly() { Document agg = newAggregation( // project().and("a").as("aa") // @@ -295,7 +295,7 @@ public void shouldRenderAggregationWithDefaultOptionsCorrectly() { } @Test // DATAMONGO-960 - public void shouldRenderAggregationWithCustomOptionsCorrectly() { + void shouldRenderAggregationWithCustomOptionsCorrectly() { AggregationOptions aggregationOptions = newAggregationOptions().explain(true).cursor(new Document("foo", 1)) .allowDiskUse(true).build(); @@ -315,7 +315,7 @@ public void shouldRenderAggregationWithCustomOptionsCorrectly() { } @Test // DATAMONGO-954, DATAMONGO-1585 - public void shouldSupportReferencingSystemVariables() { + void shouldSupportReferencingSystemVariables() { Document agg = newAggregation( // project("someKey") // @@ -336,7 +336,7 @@ public void shouldSupportReferencingSystemVariables() { } @Test // DATAMONGO-1254 - public void shouldExposeAliasedFieldnameForProjectionsIncludingOperationsDownThePipeline() { + void shouldExposeAliasedFieldnameForProjectionsIncludingOperationsDownThePipeline() { Document agg = Aggregation.newAggregation(// project("date") // @@ -350,7 +350,7 @@ public void shouldExposeAliasedFieldnameForProjectionsIncludingOperationsDownThe } @Test // DATAMONGO-1254 - public void shouldUseAliasedFieldnameForProjectionsIncludingOperationsDownThePipelineWhenUsingSpEL() { + void shouldUseAliasedFieldnameForProjectionsIncludingOperationsDownThePipelineWhenUsingSpEL() { Document agg = Aggregation.newAggregation(// project("date") // @@ -364,7 +364,7 @@ public void shouldUseAliasedFieldnameForProjectionsIncludingOperationsDownThePip } @Test // DATAMONGO-861 - public void conditionExpressionBasedFieldsShouldBeReferencableInFollowingOperations() { + void conditionExpressionBasedFieldsShouldBeReferencableInFollowingOperations() { Document agg = newAggregation( // project("a", "answer"), // @@ -382,7 +382,7 @@ public void conditionExpressionBasedFieldsShouldBeReferencableInFollowingOperati } @Test // DATAMONGO-861 - public void shouldRenderProjectionConditionalExpressionCorrectly() { + void shouldRenderProjectionConditionalExpressionCorrectly() { Document agg = Aggregation.newAggregation(// project().and(ConditionalOperators.Cond.newBuilder() // @@ -401,7 +401,7 @@ public void shouldRenderProjectionConditionalExpressionCorrectly() { } @Test // DATAMONGO-861 - public void shouldRenderProjectionConditionalCorrectly() { + void shouldRenderProjectionConditionalCorrectly() { Document agg = Aggregation.newAggregation(// project().and("color").applyCondition(ConditionalOperators.Cond.newBuilder() // @@ -420,7 +420,7 @@ public void shouldRenderProjectionConditionalCorrectly() { } @Test // DATAMONGO-861 - public void shouldRenderProjectionConditionalWithCriteriaCorrectly() { + void shouldRenderProjectionConditionalWithCriteriaCorrectly() { Document agg = Aggregation.newAggregation(project()// .and("color")// @@ -438,7 +438,7 @@ public void shouldRenderProjectionConditionalWithCriteriaCorrectly() { } @Test // DATAMONGO-861, DATAMONGO-2242 - public void referencingProjectionAliasesShouldRenderProjectionConditionalWithFieldReferenceCorrectly() { + void referencingProjectionAliasesShouldRenderProjectionConditionalWithFieldReferenceCorrectly() { Document agg = Aggregation.newAggregation(// project().and("color").as("chroma"), project().and("luminosity") // @@ -458,7 +458,7 @@ public void referencingProjectionAliasesShouldRenderProjectionConditionalWithFie } @Test // DATAMONGO-861 - public void referencingProjectionAliasesShouldRenderProjectionConditionalWithCriteriaReferenceCorrectly() { + void referencingProjectionAliasesShouldRenderProjectionConditionalWithCriteriaReferenceCorrectly() { Document agg = Aggregation.newAggregation(// project().and("color").as("chroma"), project().and("luminosity") // @@ -477,7 +477,7 @@ public void referencingProjectionAliasesShouldRenderProjectionConditionalWithCri } @Test // DATAMONGO-861 - public void shouldRenderProjectionIfNullWithFieldReferenceCorrectly() { + void shouldRenderProjectionIfNullWithFieldReferenceCorrectly() { Document agg = Aggregation.newAggregation(// project().and("color"), // @@ -493,7 +493,7 @@ public void shouldRenderProjectionIfNullWithFieldReferenceCorrectly() { } @Test // DATAMONGO-861 - public void shouldRenderProjectionIfNullWithFallbackFieldReferenceCorrectly() { + void shouldRenderProjectionIfNullWithFallbackFieldReferenceCorrectly() { Document agg = Aggregation.newAggregation(// project("fallback").and("color").as("chroma"), project().and("luminosity") // @@ -507,7 +507,7 @@ public void shouldRenderProjectionIfNullWithFallbackFieldReferenceCorrectly() { } @Test // DATAMONGO-1552 - public void shouldHonorDefaultCountField() { + void shouldHonorDefaultCountField() { Document agg = Aggregation.newAggregation(// bucket("year"), // @@ -520,7 +520,7 @@ public void shouldHonorDefaultCountField() { } @Test // DATAMONGO-1533 - public void groupOperationShouldAllowUsageOfDerivedSpELAggregationExpression() { + void groupOperationShouldAllowUsageOfDerivedSpELAggregationExpression() { Document agg = newAggregation( // project("a"), // @@ -538,7 +538,7 @@ public void groupOperationShouldAllowUsageOfDerivedSpELAggregationExpression() { } @Test // DATAMONGO-1756 - public void projectOperationShouldRenderNestedFieldNamesCorrectly() { + void projectOperationShouldRenderNestedFieldNamesCorrectly() { Document agg = newAggregation(project().and("value1.value").plus("value2.value").as("val")).toDocument("collection", Aggregation.DEFAULT_CONTEXT); @@ -548,7 +548,7 @@ public void projectOperationShouldRenderNestedFieldNamesCorrectly() { } @Test // DATAMONGO-1871 - public void providedAliasShouldAllowNestingExpressionWithAliasCorrectly() { + void providedAliasShouldAllowNestingExpressionWithAliasCorrectly() { Document condition = new Document("$and", Arrays.asList(new Document("$gte", Arrays.asList("$$est.dt", "2015-12-29")), // @@ -565,7 +565,7 @@ public void providedAliasShouldAllowNestingExpressionWithAliasCorrectly() { } @Test // DATAMONGO-2377 - public void shouldAllowInternalThisAndValueReferences() { + void shouldAllowInternalThisAndValueReferences() { Document untyped = newAggregation( // Arrays.asList( // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java index 740560e3fd..9b47ae65a7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CondExpressionUnitTests.java @@ -34,28 +34,28 @@ public class CondExpressionUnitTests { @Test // DATAMONGO-861 - public void builderRejectsEmptyFieldName() { + void builderRejectsEmptyFieldName() { assertThatIllegalArgumentException().isThrownBy(() -> newBuilder().when("")); } @Test // DATAMONGO-861 - public void builderRejectsNullFieldName() { + void builderRejectsNullFieldName() { assertThatIllegalArgumentException().isThrownBy(() -> newBuilder().when((Document) null)); } @Test // DATAMONGO-861 - public void builderRejectsNullCriteriaName() { + void builderRejectsNullCriteriaName() { assertThatIllegalArgumentException().isThrownBy(() -> newBuilder().when((Criteria) null)); } @Test // DATAMONGO-861 - public void builderRejectsBuilderAsThenValue() { + void builderRejectsBuilderAsThenValue() { assertThatIllegalArgumentException().isThrownBy( () -> newBuilder().when("isYellow").then(newBuilder().when("field").then("then-value")).otherwise("otherwise")); } @Test // DATAMONGO-861, DATAMONGO-1542, DATAMONGO-2242 - public void simpleBuilderShouldRenderCorrectly() { + void simpleBuilderShouldRenderCorrectly() { Cond operator = ConditionalOperators.when("isYellow").thenValueOf("bright").otherwise("dark"); Document document = operator.toDocument(Aggregation.DEFAULT_CONTEXT); @@ -69,7 +69,7 @@ public void simpleBuilderShouldRenderCorrectly() { } @Test // DATAMONGO-861, DATAMONGO-1542, DATAMONGO-2242 - public void simpleCriteriaShouldRenderCorrectly() { + void simpleCriteriaShouldRenderCorrectly() { Cond operator = ConditionalOperators.when(Criteria.where("luminosity").gte(100)).thenValueOf("bright") .otherwise("dark"); @@ -84,7 +84,7 @@ public void simpleCriteriaShouldRenderCorrectly() { } @Test // DATAMONGO-861, DATAMONGO-2242 - public void andCriteriaShouldRenderCorrectly() { + void andCriteriaShouldRenderCorrectly() { Cond operator = ConditionalOperators.when(Criteria.where("luminosity").gte(100) // .andOperator(Criteria.where("hue").is(50), // @@ -106,7 +106,7 @@ public void andCriteriaShouldRenderCorrectly() { } @Test // DATAMONGO-861, DATAMONGO-1542, DATAMONGO-2242 - public void twoArgsCriteriaShouldRenderCorrectly() { + void twoArgsCriteriaShouldRenderCorrectly() { Criteria criteria = Criteria.where("luminosity").gte(100) // .and("saturation").and("chroma").is(200); @@ -126,7 +126,7 @@ public void twoArgsCriteriaShouldRenderCorrectly() { } @Test // DATAMONGO-861, DATAMONGO-1542 - public void nestedCriteriaShouldRenderCorrectly() { + void nestedCriteriaShouldRenderCorrectly() { Cond operator = ConditionalOperators.when(Criteria.where("luminosity").gte(100)) // .thenValueOf(newBuilder() // From 4f75fec5c57185f3546b1588174eea1c7c5a2f9b Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 10 Jan 2020 11:22:49 +0100 Subject: [PATCH 0023/1381] DATAMONGO-2447 - Upgrade MongoDB Drivers to 3.12.0 (sync) and 1.13.0 (reactive). --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ff7167ef1d..6db92a46d4 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,8 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 3.11.2 - 1.12.0 + 3.12.0 + 1.13.0 1.19 From 7b1a96f4a942db5caa36aa47d4ad2b2b7f016b8d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 13 Jan 2020 09:05:16 +0100 Subject: [PATCH 0024/1381] DATAMONGO-2448 - Bump version to 3.0 SNAPSHOT. In preparation for the upcoming breaking changes when switching to the MongoDB Java Driver 4.0 and the breaking changes required for that update (expected for Milestone 2), we eagerly bump the version number to 3.0. Original pull request: #819. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- .../data/mongodb/core/CountQuery.java | 2 +- .../core/ExecutableUpdateOperation.java | 2 +- .../data/mongodb/core/MongoOperations.java | 26 +- .../mongodb/core/ReactiveMongoOperations.java | 26 +- .../mongodb/core/ReactiveUpdateOperation.java | 2 +- .../mongodb/core/aggregation/Aggregation.java | 2 +- .../core/aggregation/AggregationOptions.java | 6 +- .../core/aggregation/AggregationUpdate.java | 2 +- .../core/aggregation/ArithmeticOperators.java | 6 +- ...dTypeBasedAggregationOperationContext.java | 2 +- .../aggregation/ReplaceRootOperation.java | 2 +- .../aggregation/ReplaceWithOperation.java | 2 +- .../core/aggregation/SetOperation.java | 6 +- .../core/aggregation/UnsetOperation.java | 2 +- .../main/resources/META-INF/spring.schemas | 5 +- .../data/mongodb/config/spring-mongo-3.0.xsd | 708 ++++++++++++++++++ .../test/util/EnableIfMongoServerVersion.java | 2 +- .../util/EnableIfReplicaSetAvailable.java | 2 +- .../mongodb/test/util/MongoTestUtils.java | 4 +- src/main/asciidoc/new-features.adoc | 4 +- 24 files changed, 765 insertions(+), 56 deletions(-) create mode 100644 spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd diff --git a/pom.xml b/pom.xml index 6db92a46d4..7d73b4d2d4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 2.3.0.BUILD-SNAPSHOT + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index c4766040c1..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 2.3.0.BUILD-SNAPSHOT + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index ed39c63e76..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 2.3.0.BUILD-SNAPSHOT + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 25cf02b5d5..95beb40e3c 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 2.3.0.BUILD-SNAPSHOT + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java index ee2c7368a8..66b6a37b85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java @@ -34,7 +34,7 @@ * * @author Christoph Strobl * @author Mark Paluch - * @since 2.3 + * @since 3.0 */ class CountQuery { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index 414a1b7dc2..7155551b86 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -158,7 +158,7 @@ interface UpdateWithUpdate { * @param update must not be {@literal null}. * @return new instance of {@link TerminatingUpdate}. * @throws IllegalArgumentException if update is {@literal null}. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index a93670cd03..635ec96d94 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -888,7 +888,7 @@ default List findDistinct(Query query, String field, String collection, C * @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}. * @param entityClass the parametrized type. Must not be {@literal null}. * @return the converted object that was updated before it was updated or {@literal null}, if not found. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -905,7 +905,7 @@ default List findDistinct(Query query, String field, String collection, C * @param entityClass the parametrized type. Must not be {@literal null}. * @param collectionName the collection to query. Must not be {@literal null}. * @return the converted object that was updated before it was updated or {@literal null}, if not found. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -925,7 +925,7 @@ default List findDistinct(Query query, String field, String collection, C * @return the converted object that was updated or {@literal null}, if not found. Depending on the value of * {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as * it is after the update. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -946,7 +946,7 @@ default List findDistinct(Query query, String field, String collection, C * @return the converted object that was updated or {@literal null}, if not found. Depending on the value of * {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as * it is after the update. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1308,7 +1308,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the existing object. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1329,7 +1329,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the existing object. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1346,7 +1346,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1362,7 +1362,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the existing. Must not be {@literal null}. * @param entityClass class that determines the collection to use. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1384,7 +1384,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1401,7 +1401,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1417,7 +1417,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1436,7 +1436,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1453,7 +1453,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 56e5b088b2..1eb5df3d7b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -683,7 +683,7 @@ default Flux findDistinct(Query query, String field, String collection, C * @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}. * @param entityClass the parametrized type. Must not be {@literal null}. * @return the converted object that was updated before it was updated. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -699,7 +699,7 @@ default Flux findDistinct(Query query, String field, String collection, C * @param entityClass the parametrized type. Must not be {@literal null}. * @param collectionName the collection to query. Must not be {@literal null}. * @return the converted object that was updated before it was updated. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -717,7 +717,7 @@ default Flux findDistinct(Query query, String field, String collection, C * @param entityClass the parametrized type. * @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()} * this will either be the object as it was before the update or as it is after the update. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -736,7 +736,7 @@ default Flux findDistinct(Query query, String field, String collection, C * @param collectionName the collection to query. Must not be {@literal null}. * @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()} * this will either be the object as it was before the update or as it is after the update. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1171,7 +1171,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * the existing object. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1190,7 +1190,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * the existing object. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1207,7 +1207,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1225,7 +1225,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * the existing. Must not be {@literal null}. * @param entityClass class that determines the collection to use. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1246,7 +1246,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1263,7 +1263,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1279,7 +1279,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1298,7 +1298,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ @@ -1315,7 +1315,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java index 6c7e6b6252..0bb6d23c00 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java @@ -125,7 +125,7 @@ interface UpdateWithUpdate { * @param update must not be {@literal null}. * @return new instance of {@link TerminatingUpdate}. Never {@literal null}. * @throws IllegalArgumentException if update is {@literal null}. - * @since 2.3 + * @since 3.0 * @see Update * @see AggregationUpdate */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 7229c8339a..c7e8c1b2cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -120,7 +120,7 @@ public static Aggregation newAggregation(AggregationOperation... operations) { * * @param operations can be {@literal empty} but must not be {@literal null}. * @return new instance of {@link AggregationUpdate}. - * @since 2.3 + * @since 3.0 */ public static AggregationUpdate newUpdate(AggregationOperation... operations) { return AggregationUpdate.from(Arrays.asList(operations)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 381fa15ab3..39ad590d99 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -215,7 +215,7 @@ public Optional getComment() { /** * @return the time limit for processing. {@link Duration#ZERO} is used for the default unbounded behavior. - * @since 2.3 + * @since 3.0 */ public Duration getMaxTime() { return maxTime; @@ -279,7 +279,7 @@ public Document toDocument() { /** * @return - * @since 2.3 + * @since 3.0 */ public boolean hasExecutionTimeLimit() { return !maxTime.isZero() && !maxTime.isNegative(); @@ -393,7 +393,7 @@ public Builder comment(@Nullable String comment) { * @param maxTime {@link Duration#ZERO} is used for the default unbounded behavior. {@link Duration#isNegative() * Negative} values will be ignored. * @return this. - * @sinve 2.3 + * @since 3.0 */ public Builder maxTime(@Nullable Duration maxTime) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index e8201e4ba4..5866f2a1eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -74,7 +74,7 @@ * @see MongoDB * Reference Documentation - * @since 2.3 + * @since 3.0 */ public class AggregationUpdate extends Aggregation implements UpdateDefinition { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index fa21ccb955..9cda3ffcda 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -516,7 +516,7 @@ public StdDevSamp stdDevSamp() { * place. * * @return new instance of {@link Round}. - * @since 2.3 + * @since 3.0 */ public Round round() { return usesFieldRef() ? Round.roundValueOf(fieldReference) : Round.roundValueOf(expression); @@ -526,7 +526,7 @@ public Round round() { * Creates new {@link AggregationExpression} that rounds a number to a specified decimal place. * * @return new instance of {@link Round}. - * @since 2.3 + * @since 3.0 */ public Round roundToPlace(int place) { return round().place(place); @@ -1455,7 +1455,7 @@ public static Trunc truncValueOf(Number value) { * decimal. * * - * @since 2.3 + * @since 3.0 */ public static class Round extends AbstractAggregationExpression { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java index af81ca3de9..2c53c275a7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java @@ -29,7 +29,7 @@ * {@link InvalidPersistentPropertyPath} exceptions when resolving mapped field names. * * @author Christoph Strobl - * @since 2.3 + * @since 3.0 */ public class RelaxedTypeBasedAggregationOperationContext extends TypeBasedAggregationOperationContext { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index 7eed7a0683..0bf5341c37 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -98,7 +98,7 @@ public ExposedFields getFields() { * Obtain the {@link Replacement}. * * @return never {@literal null}. - * @since 2.3 + * @since 3.0 */ protected Replacement getReplacement() { return replacement; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java index e341cf4ecf..60bdcdc3ae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java @@ -27,7 +27,7 @@ * possible to promote an embedded document to the top-level or specify a new document. * * @author Christoph Strobl - * @since 2.3 + * @since 3.0 * @see MongoDB Aggregation * Framework: $replaceWith */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index 61657450ae..d7b97297ef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -37,7 +37,7 @@ * * * @author Christoph Strobl - * @since 2.3 + * @since 3.0 * @see MongoDB Aggregation Framework: * $set */ @@ -180,7 +180,7 @@ private static Object computeValue(Object value, AggregationOperationContext con /** * @author Christoph Strobl - * @since 2.3 + * @since 3.0 */ public static class FieldAppender { @@ -226,7 +226,7 @@ private SetOperation build() { /** * @author Christoph Strobl - * @since 2.3 + * @since 3.0 */ public interface ValueAppender { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java index 5a62b5c504..abd62c5b56 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java @@ -30,7 +30,7 @@ * Removes fields from documents. * * @author Christoph Strobl - * @since 2.3 + * @since 3.0 * @see MongoDB Aggregation Framework: * $unset */ diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index bcc150e5f8..af0a45b371 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -22,5 +22,6 @@ https\://www.springframework.org/schema/data/mongo/spring-mongo-1.8.xsd=org/spri https\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.xsd=org/springframework/data/mongodb/config/spring-mongo-1.10.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-2.0.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd -https\://www.springframework.org/schema/data/mongo/spring-mongo-2.2.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd -https\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-2.2.xsd +https\://www.springframework.org/schema/data/mongo/spring-mongo-2.2.xsd=org/springframework/data/mongodb/config/spring-mongo-2.2.xsd +https\://www.springframework.org/schema/data/mongo/spring-mongo-3.0.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +https\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd new file mode 100644 index 0000000000..bc1c52091a --- /dev/null +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd @@ -0,0 +1,708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Enables creation of indexes for queries that get derived from the method name + and thus reference domain class properties. Defaults to false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + The reference to a MongoTypeMapper to be used by this MappingMongoConverter. + + + + + + + The reference to a MappingContext. Will default to 'mappingContext'. + + + + + + + Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false. + + + + + + + + + + Enables abbreviating the field names for domain class properties to the + first character of their camel case names, e.g. fooBar -> fb. Defaults to false. + + + + + + + + + + The reference to a FieldNamingStrategy. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A reference to a custom converter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java index 1f5bdff616..9bd99945eb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java @@ -25,7 +25,7 @@ /** * @author Christoph Strobl - * @since 2.3 + * @since 3.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java index 16e0141933..78f965ca85 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java @@ -28,7 +28,7 @@ * replicaSet mode. Intended to be used along with {@link MongoServerCondition}. * * @author Christoph Strobl - * @since 2.3 + * @since 3.0 */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 38829da043..258f0625f1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -199,7 +199,7 @@ public static com.mongodb.reactivestreams.client.MongoClient reactiveReplSetClie /** * @return the server version extracted from buildInfo. - * @since 2.3.0 + * @since 3.0 */ public static Version serverVersion() { @@ -216,7 +216,7 @@ public static Version serverVersion() { /** * @return check if the server is running as part of a replica set. - * @since 2.3.0 + * @since 3.0 */ public static boolean serverIsReplSet() { diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 82142252ad..1f0f4cac5b 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,8 +1,8 @@ [[new-features]] = New & Noteworthy -[[new-features.2-3-0]] -== What's New in Spring Data MongoDB 2.3 +[[new-features.3.0]] +== What's New in Spring Data MongoDB 3.0 * Support for <>. * Apply pagination when using GridFS `find(Query)`. From d824f3b8b2138673ef8fba2d6be702c974521661 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 7 Jan 2020 09:01:24 +0100 Subject: [PATCH 0025/1381] DATAMONGO-2437 - Fix complex id handling when reading aggregation results. Removed Unwrapping complex id values. Template.aggregate now behaves like aggregateStream or its reactive counterpart. Original pull request: #821. --- .../data/mongodb/core/MongoTemplate.java | 35 +----- ...nwrapAndReadDocumentCallbackUnitTests.java | 101 ------------------ .../core/aggregation/AggregationTests.java | 38 +++++-- 3 files changed, 33 insertions(+), 141 deletions(-) delete mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java 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 abdf580570..88d6202d7c 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 @@ -2162,7 +2162,7 @@ protected AggregationResults aggregate(Aggregation aggregation, String co protected AggregationResults doAggregate(Aggregation aggregation, String collectionName, Class outputType, AggregationOperationContext context) { - DocumentCallback callback = new UnwrapAndReadDocumentCallback<>(mongoConverter, outputType, collectionName); + ReadDocumentCallback callback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName); AggregationOptions options = aggregation.getOptions(); AggregationUtil aggregationUtil = new AggregationUtil(queryMapper, mappingContext); @@ -3253,39 +3253,6 @@ public T doWith(@Nullable Document object) { } } - class UnwrapAndReadDocumentCallback extends ReadDocumentCallback { - - public UnwrapAndReadDocumentCallback(EntityReader reader, Class type, String collectionName) { - super(reader, type, collectionName); - } - - @Override - public T doWith(@Nullable Document object) { - - if (object == null) { - return null; - } - - Object idField = object.get(Fields.UNDERSCORE_ID); - - if (!(idField instanceof Document)) { - return super.doWith(object); - } - - Document toMap = new Document(); - Document nested = (Document) idField; - toMap.putAll(nested); - - for (String key : object.keySet()) { - if (!Fields.UNDERSCORE_ID.equals(key)) { - toMap.put(key, object.get(key)); - } - } - - return super.doWith(toMap); - } - } - class QueryCursorPreparer implements CursorPreparer { private final Query query; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java deleted file mode 100644 index 2d7d954464..0000000000 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDocumentCallbackUnitTests.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2013-2020 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 - * - * https://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.*; -import static org.mockito.Mockito.*; - -import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.MongoTemplate.UnwrapAndReadDocumentCallback; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.mapping.MongoMappingContext; - -/** - * Unit tests for {@link UnwrapAndReadDocumentCallback}. - * - * @author Oliver Gierke - * @author Mark Paluch - */ -@RunWith(MockitoJUnitRunner.class) -public class UnwrapAndReadDocumentCallbackUnitTests { - - @Mock MongoDbFactory factory; - @Mock MongoExceptionTranslator exceptionTranslatorMock; - - UnwrapAndReadDocumentCallback callback; - - @Before - public void setUp() { - - when(factory.getExceptionTranslator()).thenReturn(exceptionTranslatorMock); - - MongoTemplate template = new MongoTemplate(factory); - MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), - new MongoMappingContext()); - - this.callback = template.new UnwrapAndReadDocumentCallback(converter, Target.class, "collection-1"); - } - - @Test - public void usesFirstLevelValues() { - - Target target = callback.doWith(new Document("foo", "bar")); - - assertThat(target.id).isNull(); - assertThat(target.foo).isEqualTo("bar"); - } - - @Test - public void unwrapsUnderscoreIdIfDocument() { - - Target target = callback.doWith(new Document("_id", new Document("foo", "bar"))); - - assertThat(target.id).isNull(); - assertThat(target.foo).isEqualTo("bar"); - } - - @Test - public void firstLevelPropertiesTrumpNestedOnes() { - - Target target = callback.doWith(new Document("_id", new Document("foo", "bar")).append("foo", "foobar")); - - assertThat(target.id).isNull(); - assertThat(target.foo).isEqualTo("foobar"); - } - - @Test - public void keepsUnderscoreIdIfScalarValue() { - - Target target = callback.doWith(new Document("_id", "bar").append("foo", "foo")); - - assertThat(target.id).isEqualTo("bar"); - assertThat(target.foo).isEqualTo("foo"); - } - - static class Target { - - String id; - String foo; - } -} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index bb477c6fa4..87cd54848d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -1823,7 +1823,7 @@ public void bucketShouldCollectDocumentsIntoABucket() { assertThat((Double) bound100.get("sum")).isCloseTo(3672.9, Offset.offset(0.1D)); } - @Test // DATAMONGO-1552 + @Test // DATAMONGO-1552, DATAMONGO-2437 @MongoVersion(asOf = "3.4") public void bucketAutoShouldCollectDocumentsIntoABucket() { @@ -1844,14 +1844,14 @@ public void bucketAutoShouldCollectDocumentsIntoABucket() { AggregationResults result = mongoTemplate.aggregate(aggregation, Document.class); assertThat(result.getMappedResults().size()).isEqualTo(3); - // { "min" : 680.0 , "max" : 820.0 , "count" : 1 , "titles" : [ "Dancer"] , "sum" : 760.4000000000001} + // { "_id" : { "min" : 680.0 , "max" : 820.0 }, "count" : 1 , "titles" : [ "Dancer"] , "sum" : 760.4000000000001} Document bound0 = result.getMappedResults().get(0); - assertThat(bound0).containsEntry("count", 1).containsEntry("titles.[0]", "Dancer").containsEntry("min", 680.0) - .containsKey("max"); + assertThat(bound0).containsEntry("count", 1).containsEntry("titles.[0]", "Dancer").containsEntry("_id.min", 680.0) + .containsKey("_id.max"); - // { "min" : 820.0 , "max" : 1800.0 , "count" : 1 , "titles" : [ "The Great Wave off Kanagawa"] , "sum" : 1673.0} + // { "_id" : { "min" : 820.0 , "max" : 1800.0 }, "count" : 1 , "titles" : [ "The Great Wave off Kanagawa"] , "sum" : 1673.0} Document bound1 = result.getMappedResults().get(1); - assertThat(bound1).containsEntry("count", 1).containsEntry("min", 820.0); + assertThat(bound1).containsEntry("count", 1).containsEntry("_id.min", 820.0); assertThat((List) bound1.get("titles")).contains("The Great Wave off Kanagawa"); assertThat((Double) bound1.get("sum")).isCloseTo(1673.0, Offset.offset(0.1D)); } @@ -1930,6 +1930,21 @@ public void runMatchOperationCriteriaThroughQueryMapperForUntypedAggregation() { assertThat(groupResults.getMappedResults().size()).isEqualTo(4); } + @Test // DATAMONGO-2437 + public void shouldReadComplexIdValueCorrectly() { + + WithComplexId source = new WithComplexId(); + source.id = new ComplexId(); + source.id.p1 = "v1"; + source.id.p2 = "v2"; + + mongoTemplate.save(source); + + AggregationResults result = mongoTemplate.aggregate(newAggregation(project("id")), + WithComplexId.class, WithComplexId.class); + assertThat(result.getMappedResults()).containsOnly(source); + } + private void createUsersWithReferencedPersons() { mongoTemplate.dropCollection(User.class); @@ -2231,4 +2246,15 @@ static class Art { Integer year; double price; } + + @lombok.Data + static class WithComplexId { + @Id ComplexId id; + } + + @lombok.Data + static class ComplexId { + String p1; + String p2; + } } From 284f547e993748b0c420d79cfa36447b0cc7c43a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jan 2020 09:28:46 +0100 Subject: [PATCH 0026/1381] DATAMONGO-2437 - Polishing. Mention changes in Aggregation _id handling in what's new. Reformat code. Original pull request: #821. --- .../data/mongodb/core/aggregation/AggregationTests.java | 7 ++++--- src/main/asciidoc/new-features.adoc | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index 87cd54848d..06a068dc2b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -73,7 +73,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.CloseableIterator; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; @@ -91,7 +91,7 @@ * @author Sergey Shcherbakov * @author Minsu Kim */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class AggregationTests { @@ -1849,7 +1849,8 @@ public void bucketAutoShouldCollectDocumentsIntoABucket() { assertThat(bound0).containsEntry("count", 1).containsEntry("titles.[0]", "Dancer").containsEntry("_id.min", 680.0) .containsKey("_id.max"); - // { "_id" : { "min" : 820.0 , "max" : 1800.0 }, "count" : 1 , "titles" : [ "The Great Wave off Kanagawa"] , "sum" : 1673.0} + // { "_id" : { "min" : 820.0 , "max" : 1800.0 }, "count" : 1 , "titles" : [ "The Great Wave off Kanagawa"] , "sum" : + // 1673.0} Document bound1 = result.getMappedResults().get(1); assertThat(bound1).containsEntry("count", 1).containsEntry("_id.min", 820.0); assertThat((List) bound1.get("titles")).contains("The Great Wave off Kanagawa"); diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 1f0f4cac5b..9b0a3d1ae2 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,6 +5,7 @@ == What's New in Spring Data MongoDB 3.0 * Support for <>. +* Removal of `_id` flattening for composite Id's when using `MongoTemplate` aggregations. * Apply pagination when using GridFS `find(Query)`. [[new-features.2-2-0]] From bcc2c94e036e00072ad19df43744323ee5f316aa Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jan 2020 09:29:08 +0100 Subject: [PATCH 0027/1381] DATAMONGO-2440 - Polishing. Replace SpringJUnit4ClassRunner with SpringRunner. Original pull request: #821. --- .../data/mongodb/ReactiveTransactionIntegrationTests.java | 4 ++-- .../data/mongodb/config/AbstractIntegrationTests.java | 4 ++-- .../config/AuditingViaJavaConfigRepositoriesTests.java | 4 ++-- .../config/GeoJsonConfigurationIntegrationTests.java | 4 ++-- .../config/MongoDbFactoryNoDatabaseRunningTests.java | 4 ++-- .../data/mongodb/config/MongoNamespaceReplicaSetTests.java | 4 ++-- .../data/mongodb/config/MongoNamespaceTests.java | 4 ++-- .../mongodb/core/DefaultBulkOperationsIntegrationTests.java | 4 ++-- .../core/DefaultIndexOperationsIntegrationTests.java | 4 ++-- .../mongodb/core/DefaultReactiveIndexOperationsTests.java | 4 ++-- .../data/mongodb/core/DefaultScriptOperationsTests.java | 4 ++-- .../data/mongodb/core/MongoAdminIntegrationTests.java | 4 ++-- .../data/mongodb/core/MongoTemplateCollationTests.java | 4 ++-- .../data/mongodb/core/MongoTemplateMappingTests.java | 4 ++-- .../data/mongodb/core/MongoTemplateTests.java | 4 ++-- .../data/mongodb/core/MongoTemplateTransactionTests.java | 4 ++-- .../data/mongodb/core/MongoTemplateValidationTests.java | 4 ++-- .../data/mongodb/core/NoExplicitIdTests.java | 4 ++-- .../mongodb/core/ReactiveMongoTemplateCollationTests.java | 4 ++-- .../mongodb/core/ReactiveMongoTemplateExecuteTests.java | 4 ++-- .../data/mongodb/core/ReactiveMongoTemplateIndexTests.java | 4 ++-- .../data/mongodb/core/ReactiveMongoTemplateTests.java | 4 ++-- .../mongodb/core/aggregation/ReactiveAggregationTests.java | 4 ++-- .../SpelExpressionTransformerIntegrationTests.java | 4 ++-- .../mongodb/core/auditing/MongoTemplateAuditingTests.java | 4 ++-- .../core/auditing/ReactiveMongoTemplateAuditingTests.java | 4 ++-- .../core/convert/MongoConvertersIntegrationTests.java | 4 ++-- .../data/mongodb/core/geo/AbstractGeoSpatialTests.java | 4 ++-- .../springframework/data/mongodb/core/geo/GeoJsonTests.java | 4 ++-- .../data/mongodb/core/index/IndexingIntegrationTests.java | 4 ++-- .../MongoPersistentEntityIndexCreatorIntegrationTests.java | 4 ++-- .../data/mongodb/core/mapping/GeoIndexedTests.java | 4 ++-- .../mapping/event/ValidatingMongoEventListenerTests.java | 4 ++-- .../data/mongodb/core/mapreduce/GroupByTests.java | 4 ++-- .../data/mongodb/core/mapreduce/MapReduceTests.java | 6 +++--- .../data/mongodb/core/mapreduce/ReactiveMapReduceTests.java | 4 ++-- .../data/mongodb/core/schema/MongoJsonSchemaTests.java | 4 ++-- .../mongodb/core/schema/ReactiveMongoJsonSchemaTests.java | 4 ++-- .../data/mongodb/gridfs/GridFsTemplateIntegrationTests.java | 4 ++-- .../data/mongodb/monitor/MongoMonitorIntegrationTests.java | 4 ++-- .../AbstractPersonRepositoryIntegrationTests.java | 4 ++-- .../repository/ComplexIdRepositoryIntegrationTests.java | 4 ++-- .../repository/ContactRepositoryIntegrationTests.java | 4 ++-- .../repository/ConvertingReactiveMongoRepositoryTests.java | 4 ++-- .../MongoRepositoryTextSearchIntegrationTests.java | 4 ++-- .../PersonRepositoryLazyLoadingIntegrationTests.java | 4 ++-- .../repository/PersonRepositoryTransactionalTests.java | 4 ++-- .../mongodb/repository/ReactiveMongoRepositoryTests.java | 4 ++-- .../repository/RepositoryIndexCreationIntegrationTests.java | 4 ++-- .../repository/SimpleReactiveMongoRepositoryTests.java | 4 ++-- .../config/MongoRepositoriesRegistrarIntegrationTests.java | 4 ++-- .../ReactiveMongoRepositoriesRegistrarIntegrationTests.java | 4 ++-- .../AllowNestedMongoRepositoriesRepositoryConfigTests.java | 4 ++-- .../config/lazy/NestedMongoRepositoriesJavaConfigTests.java | 4 ++-- .../custom/ComposedRepositoryImplementationTests.java | 4 ++-- .../custom/CustomReactiveRepositoryImplementationTests.java | 4 ++-- .../custom/CustomRepositoryImplementationTests.java | 4 ++-- .../QuerydslMongoPredicateExecutorIntegrationTests.java | 4 ++-- .../repository/support/QuerydslRepositorySupportTests.java | 4 ++-- .../repository/support/SimpleMongoRepositoryTests.java | 4 ++-- .../support/SimpleMongoRepositoryVersionedEntityTests.java | 4 ++-- .../SimpleReactiveMongoRepositoryVersionedEntityTests.java | 4 ++-- .../data/mongodb/test/util/MongoVersionRule.java | 6 +++--- 63 files changed, 128 insertions(+), 128 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index 8b3ef1f818..763d0e148c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -44,7 +44,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.data.util.Version; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.reactive.TransactionalOperator; import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -58,7 +58,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class ReactiveTransactionIntegrationTests { public static @ClassRule RuleChain TEST_RULES = RuleChain.outerRule(MongoVersionRule.atLeast(Version.parse("4.0.0"))) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 0fc5425063..92e8ed602d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -29,7 +29,7 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoClient; @@ -39,7 +39,7 @@ /** * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public abstract class AbstractIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java index 58d8f7b213..174006735a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java @@ -41,7 +41,7 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.stereotype.Repository; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; @@ -52,7 +52,7 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class AuditingViaJavaConfigRepositoriesTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java index 5ce8e2c3c2..1332f3adba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/GeoJsonConfigurationIntegrationTests.java @@ -25,14 +25,14 @@ import org.springframework.data.mongodb.core.geo.GeoJsonModule; import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for {@link GeoJsonConfiguration}. * * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class GeoJsonConfigurationIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java index 63f97dca37..013dd60d73 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java @@ -25,7 +25,7 @@ import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for {@link MongoDbFactory}. @@ -33,7 +33,7 @@ * @author Thomas Risberg * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoDbFactoryNoDatabaseRunningTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java index 65b0b2c54a..a3f1c89847 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.core.MongoClientFactoryBean; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.MongoClient; @@ -45,7 +45,7 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoNamespaceReplicaSetTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index 4b2cedeb00..f37fba8631 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -31,7 +31,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.gridfs.GridFsOperations; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; @@ -46,7 +46,7 @@ * @author Thomas Darimont * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoNamespaceTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java index 03cadacf12..982c2374af 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java @@ -38,7 +38,7 @@ import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.util.Pair; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoBulkWriteException; import com.mongodb.WriteConcern; @@ -52,7 +52,7 @@ * @author Christoph Strobl * @author Minsu Kim */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class DefaultBulkOperationsIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java index 3ccf2403e8..9876ba493d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java @@ -36,7 +36,7 @@ import org.springframework.data.mongodb.core.query.Collation.CaseFirst; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ObjectUtils; import com.mongodb.client.MongoCollection; @@ -49,7 +49,7 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class DefaultIndexOperationsIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index 7205794af1..dedf2aafc5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -42,7 +42,7 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; @@ -52,7 +52,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class DefaultReactiveIndexOperationsTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java index 25060624d9..6f6c8d9f1b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java @@ -36,7 +36,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; @@ -47,7 +47,7 @@ * @author Oliver Gierke * @since 1.7 */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class DefaultScriptOperationsTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java index de5be15a25..d4b376767a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java @@ -22,7 +22,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.DB; import com.mongodb.MongoClient; @@ -32,7 +32,7 @@ * * @author Mark Pollack */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class MongoAdminIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java index 29e1346eb8..f01fd6cde9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java @@ -34,7 +34,7 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; @@ -42,7 +42,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class MongoTemplateCollationTests { public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_4_0 = MongoVersionRule.atLeast(Version.parse("3.4.0")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java index cfffce144f..fbfbf39a0b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateMappingTests.java @@ -32,7 +32,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; @@ -48,7 +48,7 @@ * @author Thomas Risberg * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:template-mapping.xml") public class MongoTemplateMappingTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index bc1ae71c5b..769ebef038 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -92,7 +92,7 @@ import org.springframework.data.util.CloseableIterator; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -127,7 +127,7 @@ * @author Laszlo Csontos * @author duozhilin */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class MongoTemplateTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index 10cff86d06..8f1cd6e0a1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -47,7 +47,7 @@ import org.springframework.data.util.Version; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.transaction.AfterTransaction; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.transaction.annotation.Transactional; @@ -61,7 +61,7 @@ * @author Christoph Strobl * @currentRead Shadow's Edge - Brent Weeks */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration @Transactional(transactionManager = "txManager") public class MongoTemplateTransactionTests { 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 index 8a2da30c0b..166463272d 100644 --- 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 @@ -41,7 +41,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.lang.Nullable; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; import com.mongodb.client.model.ValidationAction; @@ -55,7 +55,7 @@ * @author Andreas Zink * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class MongoTemplateValidationTests { public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_2_0 = MongoVersionRule.atLeast(Version.parse("3.2.0")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java index 27be2abfce..a4398ce899 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; @@ -42,7 +42,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class NoExplicitIdTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java index f600407892..d94b0e1836 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java @@ -37,7 +37,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; @@ -45,7 +45,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ReactiveMongoTemplateCollationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java index 15dca96ab8..0e78e06ef8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateExecuteTests.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.UncategorizedMongoDbException; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.ReadPreference; @@ -44,7 +44,7 @@ * * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") public class ReactiveMongoTemplateExecuteTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index 100ce97bdc..4be37b3f0a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -42,7 +42,7 @@ import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.model.IndexOptions; import com.mongodb.reactivestreams.client.ListIndexesPublisher; @@ -54,7 +54,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") public class ReactiveMongoTemplateIndexTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index 719ceb243e..0c8abe2d5e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -82,7 +82,7 @@ import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.WriteConcern; @@ -92,7 +92,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") public class ReactiveMongoTemplateTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java index 7125ba8006..262750e631 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java @@ -37,7 +37,7 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration test for aggregation via {@link org.springframework.data.mongodb.core.ReactiveMongoTemplate}. @@ -45,7 +45,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") public class ReactiveAggregationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java index 7cdc714b2b..388ec02bdf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java @@ -30,14 +30,14 @@ import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for {@link SpelExpressionTransformer}. * * @author Thomas Darimont */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class SpelExpressionTransformerIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index 8a8cd8f54f..d162fe6cd3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -35,14 +35,14 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; /** * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class MongoTemplateAuditingTests { @Configuration diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 6813ac77fb..b0219a10b7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -40,7 +40,7 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; @@ -48,7 +48,7 @@ /** * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class ReactiveMongoTemplateAuditingTests { static final String DB_NAME = "mongo-template-audit-tests"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java index 765dd0f366..9f09d79be2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java @@ -34,7 +34,7 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for {@link MongoConverters}. @@ -43,7 +43,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class MongoConvertersIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java index 0244237d85..a03e406760 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java @@ -42,7 +42,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; @@ -51,7 +51,7 @@ * @author Christoph Strobl * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public abstract class AbstractGeoSpatialTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index 03a936c134..844e9c16bc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -49,7 +49,7 @@ import org.springframework.data.mongodb.test.util.BasicDbListBuilder; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.WriteConcern; @@ -60,7 +60,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class GeoJsonTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 69053f8386..5e585ac2ed 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -50,7 +50,7 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; @@ -62,7 +62,7 @@ * @author Jordi Llach * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class IndexingIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java index c9cdf9fc52..371bfa800e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java @@ -42,7 +42,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoCommandException; @@ -53,7 +53,7 @@ * @author Christoph Strobl * @author Thomas Darimont */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoPersistentEntityIndexCreatorIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java index e6a8364f21..4e9e5280c7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoClient; @@ -44,7 +44,7 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(classes = GeoIndexedAppConfig.class) public class GeoIndexedTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java index d2392dc791..fafe8cd90a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java @@ -28,7 +28,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration test for {@link ValidatingMongoEventListener}. @@ -37,7 +37,7 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ValidatingMongoEventListenerTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java index 7151c9dc46..f5bd71ded2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoCollection; @@ -43,7 +43,7 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class GroupByTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java index cfb2dba6e1..7f0c11b299 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java @@ -36,7 +36,7 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoCollection; @@ -48,7 +48,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class MapReduceTests { @@ -326,7 +326,7 @@ private void createContentAndVersionData() { { "_id" : 3, "document_id" : "Resume", "author" : "Author", "content" : "...", "version" : 6 } { "_id" : 4, "document_id" : "Schema", "author" : "Someone Else", "content" : "...", "version" : 0.9 } { "_id" : 5, "document_id" : "Schema", "author" : "Someone Else", "content" : "...", "version" : 1 } - + */ ContentAndVersion cv1 = new ContentAndVersion(); cv1.setDocumentId("mongoDB How-To"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java index f734a600a8..cebdf0a04c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java @@ -37,7 +37,7 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.Success; @@ -47,7 +47,7 @@ * @author Mark Paluch * @currentRead Beyond the Shadows - Brent Weeks */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") public class ReactiveMapReduceTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java index 607c5b2e30..90bec67bf2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java @@ -39,7 +39,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; @@ -53,7 +53,7 @@ * * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoJsonSchemaTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java index d4b7301c34..a0310ae8f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java @@ -40,7 +40,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; @@ -50,7 +50,7 @@ * * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ReactiveMongoJsonSchemaTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index fc5fe7fc3e..12e323bfb5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -46,7 +46,7 @@ import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.StreamUtils; import com.mongodb.MongoGridFSException; @@ -66,7 +66,7 @@ * @author Mark Paluch * @author Denis Zavedeev */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:gridfs/gridfs.xml") public class GridFsTemplateIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java index 2b666a2f57..ae4f74e0a8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoClient; @@ -35,7 +35,7 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class MongoMonitorIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index f49004114c..b4f4d824a7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -63,7 +63,7 @@ import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.mongodb.repository.SampleEvaluationContextExtension.SampleSecurityContextHolder; import org.springframework.data.querydsl.QSort; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; /** @@ -76,7 +76,7 @@ * @author Fırat KÜÇÜK * @author Edward Prentice */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public abstract class AbstractPersonRepositoryIntegrationTests { @Autowired protected PersonRepository repository; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java index 0b8a74f48c..5b5556e11f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java @@ -35,7 +35,7 @@ import org.springframework.data.mongodb.test.util.MongoVersion; import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; @@ -44,7 +44,7 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ComplexIdRepositoryIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java index 9b155de4f3..e00968e5cf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepositoryIntegrationTests.java @@ -23,7 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for {@link ContactRepository}. Mostly related to mapping inheritance. @@ -32,7 +32,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("config/MongoNamespaceIntegrationTests-context.xml") public class ContactRepositoryIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java index 80447fafc7..63d4b88546 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java @@ -47,14 +47,14 @@ import org.springframework.data.repository.reactive.RxJava2SortingRepository; import org.springframework.stereotype.Repository; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Test for {@link ReactiveMongoRepository} using reactive wrapper type conversion. * * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration(classes = ConvertingReactiveMongoRepositoryTests.Config.class) public class ConvertingReactiveMongoRepositoryTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java index 1298649bf7..f78c21a044 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java @@ -43,7 +43,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -56,7 +56,7 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoRepositoryTextSearchIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java index 496479c01d..8c3624d9c8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java @@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration test for {@link PersonRepository} for lazy loading support. @@ -38,7 +38,7 @@ * @author Oliver Gierke */ @ContextConfiguration(locations = "PersonRepositoryIntegrationTests-context.xml") -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class PersonRepositoryLazyLoadingIntegrationTests { @Autowired PersonRepository repository; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index d2b9b9c6e8..58b2162689 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -46,7 +46,7 @@ import org.springframework.lang.Nullable; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.transaction.AfterTransaction; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.transaction.annotation.Transactional; @@ -61,7 +61,7 @@ * @author Christoph Strobl * @currentRead Shadow's Edge - Brent Weeks */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration @Transactional(transactionManager = "txManager") public class PersonRepositoryTransactionalTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index 0bca9f69f3..1f92d94663 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -64,7 +64,7 @@ import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; @@ -74,7 +74,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ReactiveMongoRepositoryTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java index bc5da2dcd3..cec8ad37c0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RepositoryIndexCreationIntegrationTests.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; @@ -42,7 +42,7 @@ * * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class RepositoryIndexCreationIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java index cd213dc734..072e1ba400 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java @@ -46,7 +46,7 @@ import org.springframework.data.mongodb.repository.support.SimpleReactiveMongoRepository; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ClassUtils; /** @@ -56,7 +56,7 @@ * @author Christoph Strobl * @author Ruben J Garcia */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware, BeanFactoryAware { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java index d618703ef9..6639ae7d29 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java @@ -28,7 +28,7 @@ import org.springframework.data.mongodb.repository.PersonRepository; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoClient; @@ -37,7 +37,7 @@ * * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class MongoRepositoriesRegistrarIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java index ecb42171d9..b672180178 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java @@ -27,7 +27,7 @@ import org.springframework.data.mongodb.repository.ReactivePersonRepository; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClients; @@ -36,7 +36,7 @@ * * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ReactiveMongoRepositoriesRegistrarIntegrationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java index 8653727ebf..27a2a0c46f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/AllowNestedMongoRepositoriesRepositoryConfigTests.java @@ -23,14 +23,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.repository.config.lazy.ClassWithNestedRepository.NestedUserRepository; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration test for repository namespace configuration with nested repositories. * * @author Thomas Darimont */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("AllowNestedMongoRepositoriesRepositoryConfigTests-context.xml") public class AllowNestedMongoRepositoriesRepositoryConfigTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java index 4d3634e181..1c426a3f22 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/lazy/NestedMongoRepositoriesJavaConfigTests.java @@ -27,14 +27,14 @@ import org.springframework.data.mongodb.repository.config.lazy.ClassWithNestedRepository.NestedUserRepository; import org.springframework.data.repository.support.Repositories; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration test for the combination of JavaConfig and an {@link Repositories} wrapper. * * @author Thomas Darimont */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class NestedMongoRepositoriesJavaConfigTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java index 805cbefbd5..0ce5f834b5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java @@ -24,14 +24,14 @@ import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for composed Repository implementations. * * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class ComposedRepositoryImplementationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java index d98c464415..67fa8b272d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java @@ -28,14 +28,14 @@ import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for custom reactive Repository implementations. * * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class CustomReactiveRepositoryImplementationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java index baf65c2ff5..df1b859a5d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java @@ -28,14 +28,14 @@ import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; /** * Integration tests for custom Repository implementations. * * @author Thomas Darimont */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class CustomRepositoryImplementationTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java index 557fd6e727..2f8cc5d8f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java @@ -40,7 +40,7 @@ import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoDatabase; @@ -54,7 +54,7 @@ */ @ContextConfiguration( locations = "/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml") -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) public class QuerydslMongoPredicateExecutorIntegrationTests { @Autowired MongoOperations operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index e1dd0155fe..a3337f4c3e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -38,7 +38,7 @@ import org.springframework.data.mongodb.repository.QPerson; import org.springframework.data.mongodb.repository.User; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.StringUtils; /** @@ -48,7 +48,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class QuerydslRepositorySupportTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 3c6294fbca..8688a57686 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -52,7 +52,7 @@ import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.support.TransactionTemplate; @@ -62,7 +62,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration("classpath:infrastructure.xml") public class SimpleMongoRepositoryTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java index abfa2819d5..d56b9d1534 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java @@ -38,7 +38,7 @@ import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.data.util.ClassTypeInformation; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.support.TransactionTemplate; import com.mongodb.client.MongoClient; @@ -48,7 +48,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class SimpleMongoRepositoryVersionedEntityTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java index 61474eb4c7..416e97194f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java @@ -33,7 +33,7 @@ import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; @@ -41,7 +41,7 @@ /** * @author Mark Paluch */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class SimpleReactiveMongoRepositoryVersionedEntityTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java index 229ee0f7ef..29596def07 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java @@ -25,15 +25,15 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.springframework.data.util.Version; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; /** * {@link TestRule} verifying server tests are executed against match a given version. This one can be used as - * {@link ClassRule} eg. in context depending tests run with {@link SpringJUnit4ClassRunner} when the context would fail - * to start in case of invalid version, or as simple {@link Rule} on specific tests. + * {@link ClassRule} eg. in context depending tests run with {@link SpringRunner} when the context would fail to start + * in case of invalid version, or as simple {@link Rule} on specific tests. * * @author Christoph Strobl * @author Mark Paluch From fb499f8c698ec9763d0c4346a98031deec9971b4 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 14 Jan 2020 10:51:08 +0100 Subject: [PATCH 0028/1381] DATAMONGO-2450 - Apply array filters to bulk write. Original pull request: #820. --- .../mongodb/core/DefaultBulkOperations.java | 31 +++++++++++++++---- .../core/DefaultBulkOperationsUnitTests.java | 15 ++++++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index a1e0f21550..9c78f5fe3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -15,6 +15,9 @@ */ package org.springframework.data.mongodb.core; +import lombok.NonNull; +import lombok.Value; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -38,6 +41,8 @@ import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.core.query.UpdateDefinition; +import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; import org.springframework.data.util.Pair; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -47,9 +52,6 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.model.*; -import lombok.NonNull; -import lombok.Value; - /** * Default implementation for {@link BulkOperations}. * @@ -349,9 +351,7 @@ private BulkOperations update(Query query, Update update, boolean upsert, boolea Assert.notNull(query, "Query must not be null!"); Assert.notNull(update, "Update must not be null!"); - UpdateOptions options = new UpdateOptions(); - options.upsert(upsert); - query.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation); + UpdateOptions options = computeUpdateOptions(query, update, upsert); if (multi) { addModel(update, new UpdateManyModel<>(query.getQueryObject(), update.getUpdateObject(), options)); @@ -489,6 +489,25 @@ private static BulkWriteOptions getBulkWriteOptions(BulkMode bulkMode) { throw new IllegalStateException("BulkMode was null!"); } + /** + * @param filterQuery The {@link Query} to read a potential {@link Collation} from. Must not be {@literal null}. + * @param update The {@link Update} to apply + * @param upsert flag to indicate if document should be upserted. + * @return new instance of {@link UpdateOptions}. + */ + private static UpdateOptions computeUpdateOptions(Query filterQuery, UpdateDefinition update, boolean upsert) { + + UpdateOptions options = new UpdateOptions(); + options.upsert(upsert); + + if (update.hasArrayFilters()) { + options.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList())); + } + + filterQuery.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation); + return options; + } + /** * {@link BulkOperationContext} holds information about * {@link org.springframework.data.mongodb.core.BulkOperations.BulkMode} the entity in use as well as references to diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 9d1de31cf1..4c99339957 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyList; @@ -60,6 +60,7 @@ import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; +import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; import com.mongodb.MongoWriteException; @@ -320,6 +321,18 @@ public void writeConcernAppliedCorrectlyWhenSet() { verify(collection).withWriteConcern(eq(WriteConcern.MAJORITY)); } + @Test // DATAMONGO-2450 + public void appliesArrayFilterWhenPresent() { + + ops.updateOne(new BasicQuery("{}"), new Update().filterArray(Criteria.where("element").gte(100))).execute(); + + verify(collection).bulkWrite(captor.capture(), any()); + + UpdateOneModel updateModel = (UpdateOneModel) captor.getValue().get(0); + assertThat(updateModel.getOptions().getArrayFilters().get(0)) + .isEqualTo(new org.bson.Document("element", new Document("$gte", 100))); + } + class SomeDomainType { @Id String id; From 48f51d0fb06cd0273ecd78ca01de6ee0301e58dd Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jan 2020 10:10:58 +0100 Subject: [PATCH 0029/1381] DATAMONGO-2450 - Polishing. Replace stream with for-loop. Original pull request: #820. --- .../data/mongodb/core/DefaultBulkOperations.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index 9c78f5fe3a..ee57410352 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -501,7 +501,11 @@ private static UpdateOptions computeUpdateOptions(Query filterQuery, UpdateDefin options.upsert(upsert); if (update.hasArrayFilters()) { - options.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList())); + List list = new ArrayList<>(update.getArrayFilters().size()); + for (ArrayFilter arrayFilter : update.getArrayFilters()) { + list.add(arrayFilter.asDocument()); + } + options.arrayFilters(list); } filterQuery.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation); From 3a5876537bb8a2a8d6bb32098f14ff7512a9003f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jan 2020 10:24:53 +0100 Subject: [PATCH 0030/1381] DATAMONGO-2431 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 901ab39775..310aa3f74f 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.15.RELEASE (2020-01-15) +---------------------------------------------- +* DATAMONGO-2444 - Update copyright years to 2020. +* DATAMONGO-2442 - Cond.thenValueOf(String fieldReference) does not concat fieldRef with "$" prefix. +* DATAMONGO-2431 - Release 2.1.15 (Lovelace SR15). +* DATAMONGO-2423 - @NonNullApi restricts update with null. + + Changes in version 2.2.3.RELEASE (2019-12-04) --------------------------------------------- * DATAMONGO-2430 - Upgrade to mongo-java-driver 3.11.2. @@ -2830,3 +2838,4 @@ Repository + From ab5b1f01409b301483a0692a9417522731ce40a5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 15 Jan 2020 11:19:49 +0100 Subject: [PATCH 0031/1381] DATAMONGO-2451 - Fix value conversion for id properties used in sort expression. Previously we falsely converted the sort value (1/-1) into the id types target value when a Field annotation had been present. Original pull request: #822. --- .../mongodb/core/DefaultIndexOperations.java | 4 +-- .../mongodb/core/convert/QueryMapper.java | 8 +++++- .../data/mongodb/core/MongoTemplateTests.java | 25 ++++++++++++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java index de1896b310..879c69fa29 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java @@ -127,7 +127,7 @@ public String ensureIndex(final IndexDefinition indexDefinition) { indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity); indexOptions = addDefaultCollationIfRequired(indexOptions, entity); - Document mappedKeys = mapper.getMappedObject(indexDefinition.getIndexKeys(), entity); + Document mappedKeys = mapper.getMappedSort(indexDefinition.getIndexKeys(), entity); return collection.createIndex(mappedKeys, indexOptions); }); } @@ -223,7 +223,7 @@ private IndexOptions addPartialFilterIfPresent(IndexOptions ops, Document source Assert.isInstanceOf(Document.class, sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY)); return ops.partialFilterExpression( - mapper.getMappedObject((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity)); + mapper.getMappedSort((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity)); } private static IndexOptions addDefaultCollationIfRequired(IndexOptions ops, MongoPersistentEntity entity) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index ada9adec6e..713d50b6b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -174,7 +174,13 @@ public Document getMappedSort(Document sortObject, @Nullable MongoPersistentEnti return new Document(); } - Document mappedSort = getMappedObject(sortObject, entity); + Document mappedSort = new Document(); + for(Map.Entry entry : BsonUtils.asMap(sortObject).entrySet()) { + + Field field = createPropertyField(entity, entry.getKey(), mappingContext); + mappedSort.put(field.getMappedKey(), entry.getValue()); + } + mapMetaAttributes(mappedSort, entity, MetaMapping.WHEN_PRESENT); return mappedSort; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 769ebef038..3be4e23d5b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -44,7 +44,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.convert.converter.Converter; @@ -3711,6 +3710,20 @@ public void shouldNotConvertStringToObjectIdForNonIdField() { assertThat(target.inner.id).isEqualTo(innerId); } + @Test // DATAMONGO-2451 + public void sortOnIdFieldWithExplicitTypeShouldWork() { + + template.dropCollection(WithIdAndFieldAnnotation.class); + + WithIdAndFieldAnnotation f = new WithIdAndFieldAnnotation(); + f.id = new ObjectId().toHexString(); + f.value = "value"; + + template.save(f); + + assertThat(template.find(new BasicQuery("{}").with(Sort.by("id")), WithIdAndFieldAnnotation.class)).isNotEmpty(); + } + private AtomicReference createAfterSaveReference() { AtomicReference saved = new AtomicReference<>(); @@ -4245,4 +4258,14 @@ static class Inner { @Field("id") String id; String value; } + + @Data + static class WithIdAndFieldAnnotation { + + @Id // + @Field(name = "_id") // + String id; + String value; + + } } From af133c26d0922025e299e267d15419f23f12d785 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jan 2020 12:37:09 +0100 Subject: [PATCH 0032/1381] DATAMONGO-2432 - Updated changelog. --- src/main/resources/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 310aa3f74f..a25ddbee2a 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,17 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.4.RELEASE (2020-01-15) +--------------------------------------------- +* DATAMONGO-2451 - Value of sort direction converted to String for id fields (query, index creation). +* DATAMONGO-2450 - Bulk Operations do not support filterArray in update operations. +* DATAMONGO-2444 - Update copyright years to 2020. +* DATAMONGO-2442 - Cond.thenValueOf(String fieldReference) does not concat fieldRef with "$" prefix. +* DATAMONGO-2440 - Unable to use MongoTemplate to perform query with 'in' condition by field annotated with @Field(targetType = FieldType.OBJECT_ID). +* DATAMONGO-2432 - Release 2.2.4 (Moore SR4). +* DATAMONGO-2423 - @NonNullApi restricts update with null. + + Changes in version 2.1.15.RELEASE (2020-01-15) ---------------------------------------------- * DATAMONGO-2444 - Update copyright years to 2020. @@ -2839,3 +2850,4 @@ Repository + From cbf87e6e493f84152394c9bf592646a1145595e4 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 16 Jan 2020 16:04:59 +0100 Subject: [PATCH 0033/1381] DATAMONGO-2383 - Updated changelog. --- src/main/resources/changelog.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index a25ddbee2a..ae0d88ad80 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,37 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.M1 (2020-01-16) +---------------------------------------- +* DATAMONGO-2451 - Value of sort direction converted to String for id fields (query, index creation). +* DATAMONGO-2450 - Bulk Operations do not support filterArray in update operations. +* DATAMONGO-2448 - Bump Version to 3.0. +* DATAMONGO-2447 - Upgrade MongoDB Drivers to 3.12.0 and 1.13.0. +* DATAMONGO-2444 - Update copyright years to 2020. +* DATAMONGO-2442 - Cond.thenValueOf(String fieldReference) does not concat fieldRef with "$" prefix. +* DATAMONGO-2440 - Unable to use MongoTemplate to perform query with 'in' condition by field annotated with @Field(targetType = FieldType.OBJECT_ID). +* DATAMONGO-2437 - Grouping after aggregation returns NULL _id when mapping to a class with compound key. +* DATAMONGO-2430 - Upgrade to mongo-java-driver 3.11.2. +* DATAMONGO-2423 - @NonNullApi restricts update with null. +* DATAMONGO-2418 - Application Context Doesn't start with @Query. +* DATAMONGO-2414 - ReactiveGridFsResource.getDownloadStream(…) hang if completion happens on event loop. +* DATAMONGO-2410 - Using BasicDBObject as an entity caused java.lang.ClassCastException in runtime. +* DATAMONGO-2409 - Extension Function ReactiveFindOperation.DistinctWithProjection.asType() has wrong return type. +* DATAMONGO-2403 - ReactiveStringBasedAggregation / AggregationUtils fails on NPE because source or value is null. +* DATAMONGO-2399 - Upgrade to mongo-java-driver 3.11.1. +* DATAMONGO-2394 - nearSphere query wrongly generated with radian parameter instead of meters. +* DATAMONGO-2393 - Reading large file from ReactiveGridFsTemplate causes a stackoverflow and the code to hang. +* DATAMONGO-2392 - Reading GridFS files written with old api and custom id fails on ReactiveGridFsTemplate. +* DATAMONGO-2390 - Add maxTimeMS to AggregationOptions. +* DATAMONGO-2388 - IndexOperations.getIndexInfo() fails for index that has partialFilterExpression containing DBRef. +* DATAMONGO-2385 - Unnecessary null checks in MongoConverters. +* DATAMONGO-2383 - Release 3.0 M1 (Neumann). +* DATAMONGO-2370 - Add support for $round aggregation expression. +* DATAMONGO-2331 - Add support for Aggregations in Update. +* DATAMONGO-2059 - Replace usage of deprecated collection.count() with collection.countDocuments(). +* DATAMONGO-765 - Add support for paging and sorting on GridFSTemplate. + + Changes in version 2.2.4.RELEASE (2020-01-15) --------------------------------------------- * DATAMONGO-2451 - Value of sort direction converted to String for id fields (query, index creation). @@ -2851,3 +2882,4 @@ Repository + From fca1a79f81da215e9d243c23c296c1f8922cc46a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 16 Jan 2020 16:05:03 +0100 Subject: [PATCH 0034/1381] DATAMONGO-2383 - Prepare 3.0 M1 (Neumann). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 7d73b4d2d4..16c4bbbd2a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M1 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M1 3.12.0 1.13.0 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 9d24609c69..670194ff34 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 2.2 GA +Spring Data MongoDB 3.0 M1 Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -8,3 +8,4 @@ This product may include a number of subcomponents with separate copyright notices and license terms. Your use of the source code for the these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. + From a1fbe31551da8e5720bbe0b6387afe876de5fe55 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 16 Jan 2020 16:05:23 +0100 Subject: [PATCH 0035/1381] DATAMONGO-2383 - Release version 3.0 M1 (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 16c4bbbd2a..72548c5068 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M1 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..66d60350ef 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M1 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..1d42770d29 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M1 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 95beb40e3c..35f7c8de46 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M1 ../pom.xml From f2fb05662ff26173e42b3f7ea3db1520a781c16c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 16 Jan 2020 16:11:54 +0100 Subject: [PATCH 0036/1381] DATAMONGO-2383 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 72548c5068..16c4bbbd2a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M1 + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 66d60350ef..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M1 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 1d42770d29..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M1 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 35f7c8de46..95beb40e3c 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M1 + 3.0.0.BUILD-SNAPSHOT ../pom.xml From 44e6f5fa3f80e2de4f78f021788884b605834d02 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 16 Jan 2020 16:11:55 +0100 Subject: [PATCH 0037/1381] DATAMONGO-2383 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 16c4bbbd2a..7d73b4d2d4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.M1 + 2.3.0.BUILD-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.M1 + 2.3.0.BUILD-SNAPSHOT 3.12.0 1.13.0 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot From 62be436569acc52dc4650af800da24c4f5640903 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Jan 2020 09:38:37 +0100 Subject: [PATCH 0038/1381] DATAMONGO-2454 - Updated changelog. --- src/main/resources/changelog.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index ae0d88ad80..4e89bac199 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,11 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.M2 (2020-01-17) +---------------------------------------- +* DATAMONGO-2454 - Release 3.0 M2 (Neumann). + + Changes in version 3.0.0.M1 (2020-01-16) ---------------------------------------- * DATAMONGO-2451 - Value of sort direction converted to String for id fields (query, index creation). @@ -2883,3 +2888,4 @@ Repository + From 8394523645dfa2a67f042b89366b9abeeb589bb3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Jan 2020 09:38:43 +0100 Subject: [PATCH 0039/1381] DATAMONGO-2454 - Prepare 3.0 M2 (Neumann). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 7d73b4d2d4..9667825a5a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M2 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M2 3.12.0 1.13.0 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 670194ff34..81dd640c79 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 M1 +Spring Data MongoDB 3.0 M2 Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -9,3 +9,4 @@ separate copyright notices and license terms. Your use of the source code for the these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. + From 83307c424f2d4045af9ce4601868acd7ef4011b5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Jan 2020 09:39:03 +0100 Subject: [PATCH 0040/1381] DATAMONGO-2454 - Release version 3.0 M2 (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 9667825a5a..530cc853da 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M2 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..9516a89ee8 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M2 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..ee6ee1aa3a 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M2 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 95beb40e3c..7df7716849 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M2 ../pom.xml From 1a19e140ee0952bc82a24c02fdbeff18191b18a4 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Jan 2020 09:47:49 +0100 Subject: [PATCH 0041/1381] DATAMONGO-2454 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 530cc853da..9667825a5a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M2 + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 9516a89ee8..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M2 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index ee6ee1aa3a..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M2 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 7df7716849..95beb40e3c 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M2 + 3.0.0.BUILD-SNAPSHOT ../pom.xml From 5b8037a0adc5a092292813363b334280df53a05d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Jan 2020 09:47:50 +0100 Subject: [PATCH 0042/1381] DATAMONGO-2454 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 9667825a5a..7d73b4d2d4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.M2 + 2.3.0.BUILD-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.M2 + 2.3.0.BUILD-SNAPSHOT 3.12.0 1.13.0 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot From 5f29bee6c9fa822a446bdbb74ad44627c3b16ea5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 15 Nov 2019 11:31:13 +0100 Subject: [PATCH 0043/1381] DATAMONGO-2419 - Enable JDK 11+ builds. --- .travis.yml | 21 +- Jenkinsfile | 223 +++++++++++++++++- ci/openjdk11-mongodb-4.0/Dockerfile | 14 ++ ci/openjdk11-mongodb-4.1/Dockerfile | 14 ++ ci/openjdk11-mongodb-4.2/Dockerfile | 14 ++ ci/openjdk13-mongodb-4.0/Dockerfile | 14 ++ ci/openjdk13-mongodb-4.1/Dockerfile | 14 ++ ci/openjdk13-mongodb-4.2/Dockerfile | 14 ++ .../data/mongodb/core/MongoTemplateTests.java | 4 +- .../auditing/MongoTemplateAuditingTests.java | 5 +- .../ReactiveMongoTemplateAuditingTests.java | 7 +- .../MappingMongoConverterUnitTests.java | 4 +- 12 files changed, 330 insertions(+), 18 deletions(-) create mode 100644 ci/openjdk11-mongodb-4.0/Dockerfile create mode 100644 ci/openjdk11-mongodb-4.1/Dockerfile create mode 100644 ci/openjdk11-mongodb-4.2/Dockerfile create mode 100644 ci/openjdk13-mongodb-4.0/Dockerfile create mode 100644 ci/openjdk13-mongodb-4.1/Dockerfile create mode 100644 ci/openjdk13-mongodb-4.2/Dockerfile diff --git a/.travis.yml b/.travis.yml index a6382b7217..653e62a688 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,5 @@ language: java -jdk: - - oraclejdk8 - before_install: - mkdir -p downloads - mkdir -p var/db var/log @@ -14,6 +11,14 @@ before_install: downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongo --eval "rs.initiate({_id: 'rs0', members:[{_id: 0, host: '127.0.0.1:27017'}]});" sleep 15 +jdk: + - openjdk13 + - openjdk-ea + +matrix: + allow_failures: + - jdk: openjdk-ea + env: matrix: - MONGO_VERSION=4.1.10 @@ -23,11 +28,6 @@ env: global: - PROFILE=ci -addons: - apt: - packages: - - oracle-java8-installer - sudo: false cache: @@ -35,4 +35,7 @@ cache: - $HOME/.m2 - downloads -script: "mvn clean dependency:list test -P${PROFILE} -Dsort" +install: true + +script: + - "./mvnw clean dependency:list test -Pjava11 -Dsort -U" diff --git a/Jenkinsfile b/Jenkinsfile index 005a15456b..c4cb5fb440 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -62,10 +62,106 @@ pipeline { } } } + stage('Publish JDK 11 + MongoDB 4.0') { + when { + changeset "ci/openjdk11-mongodb-4.0/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.0", "ci/openjdk11-mongodb-4.0/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } + stage('Publish JDK 11 + MongoDB 4.1') { + when { + changeset "ci/openjdk11-mongodb-4.1/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.1", "ci/openjdk11-mongodb-4.1/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } + stage('Publish JDK 11 + MongoDB 4.2') { + when { + changeset "ci/openjdk11-mongodb-4.2/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.2", "ci/openjdk11-mongodb-4.2/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } + stage('Publish JDK 13 + MongoDB 4.0') { + when { + changeset "ci/openjdk13-mongodb-4.0/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.0", "ci/openjdk13-mongodb-4.0/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } + stage('Publish JDK 13 + MongoDB 4.1') { + when { + changeset "ci/openjdk13-mongodb-4.1/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.1", "ci/openjdk13-mongodb-4.1/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } + stage('Publish JDK 13 + MongoDB 4.2') { + when { + changeset "ci/openjdk13-mongodb-4.2/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.2", "ci/openjdk13-mongodb-4.2/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } } } - stage("test: baseline") { + stage("test: baseline (jdk8)") { when { anyOf { branch 'master' @@ -99,7 +195,47 @@ pipeline { } } parallel { - stage("test: mongodb 4.0") { + stage("test: baseline (jdk11)") { + agent { + docker { + image 'springci/spring-data-openjdk11-with-mongodb-4.2:latest' + label 'data' + args '-v $HOME:/tmp/jenkins-home' + } + } + options { timeout(time: 30, unit: 'MINUTES') } + steps { + sh 'rm -rf ?' + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + } + } + + stage("test: baseline (jdk13)") { + agent { + docker { + image 'springci/spring-data-openjdk13-with-mongodb-4.2:latest' + label 'data' + args '-v $HOME:/tmp/jenkins-home' + } + } + options { timeout(time: 30, unit: 'MINUTES') } + steps { + sh 'rm -rf ?' + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + } + } + + stage("test: mongodb 4.0 (jdk8)") { agent { docker { image 'springci/spring-data-openjdk8-with-mongodb-4.0:latest' @@ -118,7 +254,48 @@ pipeline { sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B' } } - stage("test: mongodb 4.1") { + + stage("test: mongodb 4.0 (jdk11)") { + agent { + docker { + image 'springci/spring-data-openjdk11-with-mongodb-4.0:latest' + label 'data' + args '-v $HOME:/tmp/jenkins-home' + } + } + options { timeout(time: 30, unit: 'MINUTES') } + steps { + sh 'rm -rf ?' + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + } + } + + stage("test: mongodb 4.0 (jdk13)") { + agent { + docker { + image 'springci/spring-data-openjdk13-with-mongodb-4.0:latest' + label 'data' + args '-v $HOME:/tmp/jenkins-home' + } + } + options { timeout(time: 30, unit: 'MINUTES') } + steps { + sh 'rm -rf ?' + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + } + } + + stage("test: mongodb 4.1 (jdk8)") { agent { docker { image 'springci/spring-data-openjdk8-with-mongodb-4.1:latest' @@ -137,6 +314,46 @@ pipeline { sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B' } } + + stage("test: mongodb 4.1 (jdk11)") { + agent { + docker { + image 'springci/spring-data-openjdk11-with-mongodb-4.1:latest' + label 'data' + args '-v $HOME:/tmp/jenkins-home' + } + } + options { timeout(time: 30, unit: 'MINUTES') } + steps { + sh 'rm -rf ?' + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + } + } + + stage("test: mongodb 4.1 (jdk13)") { + agent { + docker { + image 'springci/spring-data-openjdk13-with-mongodb-4.1:latest' + label 'data' + args '-v $HOME:/tmp/jenkins-home' + } + } + options { timeout(time: 30, unit: 'MINUTES') } + steps { + sh 'rm -rf ?' + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + } + } } } diff --git a/ci/openjdk11-mongodb-4.0/Dockerfile b/ci/openjdk11-mongodb-4.0/Dockerfile new file mode 100644 index 0000000000..8c450a54f5 --- /dev/null +++ b/ci/openjdk11-mongodb-4.0/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk11:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org=4.0.9 mongodb-org-server=4.0.9 mongodb-org-shell=4.0.9 mongodb-org-mongos=4.0.9 mongodb-org-tools=4.0.9 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk11-mongodb-4.1/Dockerfile b/ci/openjdk11-mongodb-4.1/Dockerfile new file mode 100644 index 0000000000..9e9fff1f52 --- /dev/null +++ b/ci/openjdk11-mongodb-4.1/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk11:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 4B7C549A058F8B6B + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.1 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.1.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org-unstable=4.1.13 mongodb-org-unstable-server=4.1.13 mongodb-org-unstable-shell=4.1.13 mongodb-org-unstable-mongos=4.1.13 mongodb-org-unstable-tools=4.1.13 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk11-mongodb-4.2/Dockerfile b/ci/openjdk11-mongodb-4.2/Dockerfile new file mode 100644 index 0000000000..03eeabb62f --- /dev/null +++ b/ci/openjdk11-mongodb-4.2/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk11:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/ci/openjdk13-mongodb-4.0/Dockerfile b/ci/openjdk13-mongodb-4.0/Dockerfile new file mode 100644 index 0000000000..511db028ab --- /dev/null +++ b/ci/openjdk13-mongodb-4.0/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk13:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org=4.0.9 mongodb-org-server=4.0.9 mongodb-org-shell=4.0.9 mongodb-org-mongos=4.0.9 mongodb-org-tools=4.0.9 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk13-mongodb-4.1/Dockerfile b/ci/openjdk13-mongodb-4.1/Dockerfile new file mode 100644 index 0000000000..5f94bb6f2b --- /dev/null +++ b/ci/openjdk13-mongodb-4.1/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk13:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 4B7C549A058F8B6B + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.1 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.1.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org-unstable=4.1.13 mongodb-org-unstable-server=4.1.13 mongodb-org-unstable-shell=4.1.13 mongodb-org-unstable-mongos=4.1.13 mongodb-org-unstable-tools=4.1.13 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk13-mongodb-4.2/Dockerfile b/ci/openjdk13-mongodb-4.2/Dockerfile new file mode 100644 index 0000000000..3f73cd4426 --- /dev/null +++ b/ci/openjdk13-mongodb-4.2/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk13:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 3be4e23d5b..7dca9fd5cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -32,6 +32,7 @@ import java.math.BigInteger; import java.time.Duration; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -3669,7 +3670,8 @@ public void writesAuditingMetadataForImmutableTypes() { ImmutableAudited read = template.findOne(query(where("id").is(result.getId())), ImmutableAudited.class); - assertThat(read.modified).isEqualTo(result.modified).describedAs("Expected auditing information to be read!"); + assertThat(read.modified).isEqualTo(result.modified.truncatedTo(ChronoUnit.MILLIS)) + .describedAs("Expected auditing information to be read!"); } @Test // DATAMONGO-1798 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index d162fe6cd3..e98a4136b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.*; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; import org.junit.Test; @@ -80,7 +81,7 @@ public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSa assertThat(updated.modificationDate).isAfter(inserted.modificationDate); assertThat(fetched.modificationDate).isAfter(inserted.modificationDate); - assertThat(fetched.modificationDate).isEqualTo(updated.modificationDate); + assertThat(fetched.modificationDate).isEqualTo(updated.modificationDate.truncatedTo(ChronoUnit.MILLIS)); } @Test // DATAMONGO-2346 @@ -101,7 +102,7 @@ public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEnti assertThat(updated.getModificationDate()).isAfter(inserted.getModificationDate()); assertThat(fetched.getModificationDate()).isAfter(inserted.getModificationDate()); - assertThat(fetched.getModificationDate()).isEqualTo(updated.getModificationDate()); + assertThat(fetched.getModificationDate()).isEqualTo(updated.getModificationDate().truncatedTo(ChronoUnit.MILLIS)); } static class ImmutableAuditableEntityWithVersion { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index b0219a10b7..3095799f73 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -22,6 +22,7 @@ import java.time.Duration; import java.time.Instant; +import java.time.temporal.ChronoUnit; import org.junit.Before; import org.junit.Test; @@ -96,7 +97,8 @@ public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSa assertThat(tuple3.getT2().modificationDate).isAfter(tuple3.getT1().modificationDate); assertThat(tuple3.getT3().modificationDate).isAfter(tuple3.getT1().modificationDate); - assertThat(tuple3.getT3().modificationDate).isEqualTo(tuple3.getT2().modificationDate); + assertThat(tuple3.getT3().modificationDate) + .isEqualTo(tuple3.getT2().modificationDate.truncatedTo(ChronoUnit.MILLIS)); }) // .verifyComplete(); } @@ -117,7 +119,8 @@ public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEnti assertThat(tuple3.getT2().getModificationDate()).isAfter(tuple3.getT1().getModificationDate()); assertThat(tuple3.getT3().getModificationDate()).isAfter(tuple3.getT1().getModificationDate()); - assertThat(tuple3.getT3().getModificationDate()).isEqualTo(tuple3.getT2().getModificationDate()); + assertThat(tuple3.getT3().getModificationDate()) + .isEqualTo(tuple3.getT2().getModificationDate().truncatedTo(ChronoUnit.MILLIS)); }) // .verifyComplete(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index b889bdf36e..5fdd8e185d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -28,6 +28,7 @@ import java.math.BigInteger; import java.net.URL; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.*; import org.bson.types.Code; @@ -1663,7 +1664,8 @@ public void convertsJava8DateTimeTypesToDateAndBack() { converter.write(source, result); assertThat(result.get("date")).isInstanceOf(Date.class); - assertThat(converter.read(TypeWithLocalDateTime.class, result).date).isEqualTo(reference); + assertThat(converter.read(TypeWithLocalDateTime.class, result).date) + .isEqualTo(reference.truncatedTo(ChronoUnit.MILLIS)); } @Test // DATAMONGO-1128 From 8b97e932a2faa9c9f98739c07858c0b408a999ae Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 10 Dec 2019 09:01:23 +0100 Subject: [PATCH 0044/1381] DATAMONGO-2427 - Upgrade to MongoDB 4.0 Driver. This change switches to the MongoDB 4.0 driver and introduces configuration options for com.mongodb.client.MongoClient. The XML namespace changed from client-options to client-settings and removed already deprecated elements and attributes. Imports are switched from single artifact uber jar to split imports for driver-core, -sync and -reactivestreams. Deprecations have been removed. Original pull request: #823. --- README.adoc | 118 ++++- pom.xml | 12 +- spring-data-mongodb/pom.xml | 25 +- .../data/mongodb/BulkOperationException.java | 10 +- .../data/mongodb/MongoDatabaseUtils.java | 6 +- .../data/mongodb/MongoDbFactory.java | 42 +- .../data/mongodb/MongoTransactionManager.java | 2 +- .../AbstractMongoClientConfiguration.java | 6 +- .../config/AbstractMongoConfiguration.java | 121 ----- .../ConnectionStringPropertyEditor.java | 46 ++ .../mongodb/config/MongoClientParser.java | 31 +- .../mongodb/config/MongoDbFactoryParser.java | 45 +- .../mongodb/config/MongoParsingUtils.java | 152 ++++-- .../config/ReadConcernPropertyEditor.java | 48 ++ .../config/WriteConcernPropertyEditor.java | 3 +- .../data/mongodb/core/MongoAdmin.java | 24 +- .../mongodb/core/MongoClientFactoryBean.java | 283 ++++++++--- .../core/MongoClientOptionsFactoryBean.java | 338 ------------- .../core/MongoClientSettingsFactoryBean.java | 464 ++++++++++++++++++ .../MongoDataIntegrityViolationException.java | 17 +- .../mongodb/core/MongoDbFactorySupport.java | 37 +- .../core/MongoExceptionTranslator.java | 6 - .../data/mongodb/core/MongoOperations.java | 46 +- .../data/mongodb/core/MongoTemplate.java | 60 +-- .../core/ReactiveMongoClientFactoryBean.java | 2 +- ...eactiveMongoClientSettingsFactoryBean.java | 184 +------ .../mongodb/core/ReactiveMongoTemplate.java | 32 +- .../data/mongodb/core/ScriptOperations.java | 1 - .../core/SimpleMongoClientDbFactory.java | 13 - .../mongodb/core/SimpleMongoDbFactory.java | 107 ---- .../core/convert/DefaultDbRefResolver.java | 6 +- .../core/mapreduce/MapReduceOptions.java | 122 +++-- .../core/mapreduce/MapReduceResults.java | 36 -- .../core/messaging/SubscriptionRequest.java | 2 +- .../data/mongodb/core/query/Meta.java | 41 +- .../data/mongodb/core/query/Query.java | 27 - .../gridfs/AsyncInputStreamAdapter.java | 6 +- .../gridfs/DataBufferPublisherAdapter.java | 3 +- .../data/mongodb/gridfs/GridFsResource.java | 9 +- .../data/mongodb/gridfs/GridFsTemplate.java | 2 +- .../data/mongodb/monitor/AbstractMonitor.java | 37 +- .../data/mongodb/monitor/AssertMetrics.java | 17 +- .../monitor/BackgroundFlushingMetrics.java | 13 +- .../mongodb/monitor/BtreeIndexCounters.java | 13 +- .../mongodb/monitor/ConnectionMetrics.java | 14 +- .../mongodb/monitor/GlobalLockMetrics.java | 13 +- .../data/mongodb/monitor/MemoryMetrics.java | 13 +- .../mongodb/monitor/OperationCounters.java | 13 +- .../data/mongodb/monitor/ServerInfo.java | 12 +- .../data/mongodb/repository/Meta.java | 16 - .../repository/query/MongoQueryMethod.java | 11 - .../util/json/ParameterBindingJsonReader.java | 19 - .../data/mongodb/config/spring-mongo-3.0.xsd | 257 +++++++--- .../java/ConfigClassInDefaultPackage.java | 13 +- .../mongodb/MongoDatabaseUtilsUnitTests.java | 2 +- .../MongoTransactionManagerUnitTests.java | 4 +- .../AbstractMongoConfigurationUnitTests.java | 18 +- ...ctReactiveMongoConfigurationUnitTests.java | 6 +- .../config/MongoClientNamespaceTests.java | 144 ++++++ .../MongoClientParserIntegrationTests.java | 70 +-- ...ongoCredentialPropertyEditorUnitTests.java | 12 - .../MongoDbFactoryParserIntegrationTests.java | 54 +- .../config/MongoNamespaceReplicaSetTests.java | 15 +- .../mongodb/config/MongoNamespaceTests.java | 58 +-- .../config/MongoParserIntegrationTests.java | 9 +- .../data/mongodb/config/MyWriteConcern.java | 57 --- .../core/DefaultBulkOperationsUnitTests.java | 2 +- .../core/DefaultIndexOperationsUnitTests.java | 2 +- .../DefaultReactiveIndexOperationsTests.java | 2 +- .../core/MongoAdminIntegrationTests.java | 5 +- .../core/MongoClientFactoryBeanUnitTests.java | 106 ++++ ...tSettingsFactoryBeanIntegrationTests.java} | 8 +- ...ngoClientSettingsFactoryBeanUnitTests.java | 66 +++ .../data/mongodb/core/MongoTemplateTests.java | 4 +- .../mongodb/core/MongoTemplateUnitTests.java | 3 +- .../core/MongoTemplateValidationTests.java | 1 - .../core/QueryCursorPreparerUnitTests.java | 57 +-- .../core/ReactiveClientSessionTests.java | 2 - ...ReactiveMongoTemplateTransactionTests.java | 8 +- .../core/ReactiveMongoTemplateUnitTests.java | 3 +- ...iveSessionBoundMongoTemplateUnitTests.java | 1 - .../ReactiveUpdateOperationSupportTests.java | 17 +- .../core/SessionBoundMongoTemplateTests.java | 4 +- .../SessionBoundMongoTemplateUnitTests.java | 1 - ... SimpleMongoClientDbFactoryUnitTests.java} | 18 +- .../SpelExpressionTransformerUnitTests.java | 9 +- .../auditing/MongoTemplateAuditingTests.java | 1 - .../DbRefMappingMongoConverterUnitTests.java | 2 +- .../DefaultDbRefResolverUnitTests.java | 2 +- .../core/convert/QueryMapperUnitTests.java | 8 +- .../core/index/IndexingIntegrationTests.java | 2 - ...PersistentEntityIndexCreatorUnitTests.java | 2 +- ...ApplicationContextEventTestsAppConfig.java | 3 +- .../mapreduce/ReactiveMapReduceTests.java | 14 +- .../DefaultMessageListenerContainerTests.java | 10 +- .../core/messaging/TailableCursorTests.java | 2 - .../gridfs/GridFsResourceUnitTests.java | 8 +- .../GridFsTemplateIntegrationTests.java | 42 +- .../gridfs/ReactiveGridFsTemplateTests.java | 43 +- .../monitor/MongoMonitorIntegrationTests.java | 2 +- .../UserWithComplexIdRepository.java | 4 +- .../repository/cdi/MongoTemplateProducer.java | 3 - ...RepositoriesRegistrarIntegrationTests.java | 3 - .../query/MongoQueryMethodUnitTests.java | 25 - .../query/StringBasedMongoQueryUnitTests.java | 8 +- .../data/mongodb/test/util/CleanMongoDB.java | 3 - .../mongodb/test/util/MongoTestUtils.java | 9 +- .../test/resources/gridfs/reactive-gridfs.xml | 2 +- .../src/test/resources/infrastructure.xml | 2 +- .../db-factory-bean-custom-write-concern.xml | 4 +- .../resources/namespace/db-factory-bean.xml | 12 +- .../test/resources/namespace/mongo-bean.xml | 6 +- .../resources/namespace/mongoClient-bean.xml | 8 +- .../MongoClientNamespaceTests-context.xml | 40 ++ ...bFactoryNoDatabaseRunningTests-context.xml | 4 +- .../MongoNamespaceReplicaSetTests-context.xml | 8 +- .../config/MongoNamespaceTests-context.xml | 22 +- .../data/mongodb/config/mongo.properties | 2 + ...rsonRepositoryIntegrationTests-context.xml | 2 +- ...MongoNamespaceIntegrationTests-context.xml | 2 +- src/main/asciidoc/index.adoc | 1 + .../client-session-transactions.adoc | 2 +- src/main/asciidoc/reference/mapping.adoc | 10 +- src/main/asciidoc/reference/migrating.adoc | 61 +++ .../asciidoc/reference/mongo-auditing.adoc | 22 +- .../reference/mongo-custom-conversions.adoc | 30 +- .../reference/mongo-repositories.adoc | 65 +-- src/main/asciidoc/reference/mongodb.adoc | 118 +++-- .../asciidoc/reference/reactive-mongodb.adoc | 8 +- src/main/asciidoc/upgrading.adoc | 123 +++++ 130 files changed, 2487 insertions(+), 2027 deletions(-) delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java delete mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java rename spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/{MongoClientOptionsFactoryBeanIntegrationTests.java => MongoClientSettingsFactoryBeanIntegrationTests.java} (86%) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java rename spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/{SimpleMongoDbFactoryUnitTests.java => SimpleMongoClientDbFactoryUnitTests.java} (84%) create mode 100644 spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml create mode 100644 src/main/asciidoc/reference/migrating.adoc create mode 100644 src/main/asciidoc/upgrading.adoc diff --git a/README.adoc b/README.adoc index e2ee15c857..820ace0073 100644 --- a/README.adoc +++ b/README.adoc @@ -50,11 +50,11 @@ public class MyService { @Configuration @EnableMongoRepositories -class ApplicationConfig extends AbstractMongoConfiguration { +class ApplicationConfig extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Override @@ -94,6 +94,120 @@ If you'd rather like the latest snapshots of the upcoming major version, use our ---- +== Upgrading from 2.x + +The 4.0 MongoDB Java Driver does no longer support certain features that have already been deprecated in one of the last minor versions. +Some of the changes affect the initial setup configuration as well as compile/runtime features. We summarized the most typical changes one might encounter. + +=== XML Namespace + +.Changed XML Namespace Elements and Attributes: +|=== +Element / Attribute | 2.x | 3.x + +| `` +| Used to create a `com.mongodb.MongoClient` +| Now exposes a `com.mongodb.client.MongoClient` + +| `` +| Was a comma delimited list of replica set members (host/port) +| Now defines the replica set name. + +Use `` instead + +| `` +| NONE, NORMAL, SAFE, FSYNC_SAFE, REPLICAS_SAFE, MAJORITY +| W1, W2, W3, UNAKNOWLEDGED, AKNOWLEDGED, JOURNALED, MAJORITY +|=== + +.Removed XML Namespace Elements and Attributes: +|=== +Element / Attribute | Replacement in 3.x | Comment + +| `` +| `` +| Referencing a `com.mongodb.client.MongoClient`. + +| `` +| `` +| Single authentication data instead of list. + +| `` +| `` +| See `com.mongodb.MongoClientSettings` for details. +|=== + +.New XML Namespace Elements and Attributes: +|=== +Element | Comment + +| `` +| Replacement for `` + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Namespace element for `com.mongodb.MongoClientSettings`. + +|=== + +=== Java Configuration + +.Java API changes +|=== +Type | Comment + +| `MongoClientFactoryBean` +| Creates `com.mongodb.client.MongoClient` instead of `com.mongodb.MongoClient` + +Uses `MongoClientSettings` instead of `MongoClientOptions`. + +| `MongoDataIntegrityViolationException` +| Uses `WriteConcernResult` instead of `WriteResult`. + +| `BulkOperationException` +| Uses `MongoBulkWriteException` and `com.mongodb.bulk.BulkWriteError` instead of `BulkWriteException` and `com.mongodb.BulkWriteError` + +| `ReactiveMongoClientFactoryBean` +| Uses `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` + +| `ReactiveMongoClientSettingsFactoryBean` +| Now produces `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` +|=== + +.Removed Java API: +|=== +2.x | Replacement in 3.x | Comment + +| `MongoClientOptionsFactoryBean` +| `MongoClientSettingsFactoryBean` +| Creating a `com.mongodb.MongoClientSettings`. + +| `AbstractMongoConfiguration` +| `AbstractMongoClientConfiguration` + +(Available since 2.1) +| Using `com.mongodb.client.MongoClient`. + +| `MongoDbFactory#getLegacyDb()` +| - +| - + +| `SimpleMongoDbFactory` +| `SimpleMongoClientDbFactory` + +(Available since 2.1) +| + +| `MapReduceOptions#getOutputType()` +| `MapReduceOptions#getMapReduceAction()` +| Returns `MapReduceAction` instead of `MapReduceCommand.OutputType`. + +| `Meta\|Query` maxScan & snapshot +| +| +|=== + == Getting Help Having trouble with Spring Data? We’d love to help! diff --git a/pom.xml b/pom.xml index 7d73b4d2d4..86fbb52cd2 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,8 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 3.12.0 - 1.13.0 + 4.0.0-SNAPSHOT + ${mongo} 1.19 @@ -127,7 +127,7 @@ org.mongodb - mongo-java-driver + mongodb-driver-core ${mongo} @@ -137,6 +137,12 @@ spring-libs-snapshot https://repo.spring.io/libs-snapshot + + sonatype-libs-snapshot + https://oss.sonatype.org/content/repositories/snapshots + false + true + diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 95beb40e3c..04cab785a3 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -65,6 +65,12 @@ querydsl-mongodb ${querydsl} true + + + org.mongodb + mongo-java-driver + + @@ -82,28 +88,19 @@ + org.mongodb - mongodb-driver-reactivestreams - ${mongo.reactivestreams} + mongodb-driver-sync + ${mongo} true org.mongodb - mongodb-driver-async - ${mongo} + mongodb-driver-reactivestreams + ${mongo.reactivestreams} true - - - org.mongodb - mongodb-driver-core - - - org.mongodb - bson - - diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java index 4435f4d4e7..eee31a1e67 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java @@ -19,9 +19,9 @@ import org.springframework.dao.DataAccessException; -import com.mongodb.BulkWriteError; -import com.mongodb.BulkWriteException; -import com.mongodb.BulkWriteResult; +import com.mongodb.MongoBulkWriteException; +import com.mongodb.bulk.BulkWriteError; +import com.mongodb.bulk.BulkWriteResult; /** * Is thrown when errors occur during bulk operations. @@ -38,12 +38,12 @@ public class BulkOperationException extends DataAccessException { private final BulkWriteResult result; /** - * Creates a new {@link BulkOperationException} with the given message and source {@link BulkWriteException}. + * Creates a new {@link BulkOperationException} with the given message and source {@link MongoBulkWriteException}. * * @param message must not be {@literal null}. * @param source must not be {@literal null}. */ - public BulkOperationException(String message, BulkWriteException source) { + public BulkOperationException(String message, MongoBulkWriteException source) { super(message, source); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index 6e3faac9b8..bd5df06688 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -105,17 +105,17 @@ private static MongoDatabase doGetMongoDatabase(@Nullable String dbName, MongoDb Assert.notNull(factory, "Factory must not be null!"); if (!TransactionSynchronizationManager.isSynchronizationActive()) { - return StringUtils.hasText(dbName) ? factory.getDb(dbName) : factory.getDb(); + return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } ClientSession session = doGetSession(factory, sessionSynchronization); if (session == null) { - return StringUtils.hasText(dbName) ? factory.getDb(dbName) : factory.getDb(); + return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } MongoDbFactory factoryToUse = factory.withSession(session); - return StringUtils.hasText(dbName) ? factoryToUse.getDb(dbName) : factoryToUse.getDb(); + return StringUtils.hasText(dbName) ? factoryToUse.getMongoDatabase(dbName) : factoryToUse.getMongoDatabase(); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index 7ad7d8f817..116d3b1f19 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -21,7 +21,6 @@ import org.springframework.data.mongodb.core.MongoExceptionTranslator; import com.mongodb.ClientSessionOptions; -import com.mongodb.DB; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoDatabase; @@ -39,34 +38,47 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi * * @return * @throws DataAccessException + * @deprecated since 3.0. Use {@link #getMongoDatabase()} instead. */ - MongoDatabase getDb() throws DataAccessException; + @Deprecated + default MongoDatabase getDb() throws DataAccessException { + return getMongoDatabase(); + } + + /** + * Obtain a {@link MongoDatabase} from the underlying factory. + * + * @return never {@literal null}. + * @throws DataAccessException + */ + MongoDatabase getMongoDatabase() throws DataAccessException; /** - * Creates a {@link DB} instance to access the database with the given name. + * Creates a {@link MongoDatabase} instance to access the database with the given name. * * @param dbName must not be {@literal null} or empty. * @return * @throws DataAccessException + * @deprecated since 3.0. Use {@link #getMongoDatabase(String)} instead. */ - MongoDatabase getDb(String dbName) throws DataAccessException; + @Deprecated + default MongoDatabase getDb(String dbName) throws DataAccessException { + return getMongoDatabase(dbName); + } /** - * Exposes a shared {@link MongoExceptionTranslator}. - * - * @return will never be {@literal null}. + * @param dbName + * @return never {@literal null}. + * @throws DataAccessException */ - PersistenceExceptionTranslator getExceptionTranslator(); + MongoDatabase getMongoDatabase(String dbName) throws DataAccessException; /** - * Get the legacy database entry point. Please consider {@link #getDb()} instead. + * Exposes a shared {@link MongoExceptionTranslator}. * - * @return - * @deprecated since 2.1, use {@link #getDb()}. This method will be removed with a future version as it works only - * with the legacy MongoDB driver. + * @return will never be {@literal null}. */ - @Deprecated - DB getLegacyDb(); + PersistenceExceptionTranslator getExceptionTranslator(); /** * Get the underlying {@link CodecRegistry} used by the MongoDB Java driver. @@ -75,7 +87,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi */ @Override default CodecRegistry getCodecRegistry() { - return getDb().getCodecRegistry(); + return getMongoDatabase().getCodecRegistry(); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java index 80fc02eeab..d4f333a043 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java @@ -45,7 +45,7 @@ * commit} or {@link ClientSession#abortTransaction() abort} a transaction. *

* Application code is required to retrieve the {@link com.mongodb.client.MongoDatabase} via - * {@link MongoDatabaseUtils#getDatabase(MongoDbFactory)} instead of a standard {@link MongoDbFactory#getDb()} call. + * {@link MongoDatabaseUtils#getDatabase(MongoDbFactory)} instead of a standard {@link MongoDbFactory#getMongoDatabase()} call. * Spring classes such as {@link org.springframework.data.mongodb.core.MongoTemplate} use this strategy implicitly. *

* By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. One may override diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index 6627cbb045..cb04fe7beb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -20,7 +20,6 @@ import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -35,7 +34,6 @@ * @author Christoph Strobl * @since 2.1 * @see MongoConfigurationSupport - * @see AbstractMongoConfiguration */ @Configuration public abstract class AbstractMongoClientConfiguration extends MongoConfigurationSupport { @@ -59,8 +57,8 @@ public MongoTemplate mongoTemplate() throws Exception { } /** - * Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient} - * instance configured in {@link #mongoClient()}. + * Creates a {@link org.springframework.data.mongodb.core.SimpleMongoDbFactory;} to be used by the + * {@link MongoTemplate}. Will use the {@link MongoClient} instance configured in {@link #mongoClient()}. * * @see #mongoClient() * @see #mongoTemplate() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java deleted file mode 100644 index a5eadefd02..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2011-2020 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 - * - * https://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.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.lang.Nullable; - -import com.mongodb.MongoClient; - -/** - * Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.MongoClient}. - *

- * INFO:In case you want to use {@link com.mongodb.client.MongoClients} for configuration please refer - * to {@link AbstractMongoClientConfiguration}. - * - * @author Mark Pollack - * @author Oliver Gierke - * @author Thomas Darimont - * @author Ryan Tenney - * @author Christoph Strobl - * @author Mark Paluch - * @see MongoConfigurationSupport - * @see AbstractMongoClientConfiguration - * @deprecated since 2.2 in favor of {@link AbstractMongoClientConfiguration}. - */ -@Configuration -@Deprecated -public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport { - - /** - * Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a - * {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}. - * - * @return - */ - public abstract MongoClient mongoClient(); - - /** - * Creates a {@link MongoTemplate}. - * - * @return - */ - @Bean - public MongoTemplate mongoTemplate() throws Exception { - return new MongoTemplate(mongoDbFactory(), mappingMongoConverter()); - } - - /** - * Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient} - * instance configured in {@link #mongoClient()}. - * - * @see #mongoClient() - * @see #mongoTemplate() - * @return - */ - @Bean - public MongoDbFactory mongoDbFactory() { - return new SimpleMongoDbFactory(mongoClient(), getDatabaseName()); - } - - /** - * Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration - * class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending - * {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is - * overridden to implement alternate behavior. - * - * @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for - * entities. - * @deprecated use {@link #getMappingBasePackages()} instead. - */ - @Deprecated - @Nullable - protected String getMappingBasePackage() { - - Package mappingBasePackage = getClass().getPackage(); - return mappingBasePackage == null ? null : mappingBasePackage.getName(); - } - - /** - * Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and - * {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied. - * - * @see #customConversions() - * @see #mongoMappingContext() - * @see #mongoDbFactory() - * @return - * @throws Exception - */ - @Bean - public MappingMongoConverter mappingMongoConverter() throws Exception { - - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); - MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext()); - converter.setCustomConversions(customConversions()); - converter.setCodecRegistryProvider(mongoDbFactory()); - - return converter; - } - -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java new file mode 100644 index 0000000000..3fd9017ef9 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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 + * + * https://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.config; + +import java.beans.PropertyEditorSupport; + +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import com.mongodb.ConnectionString; + +/** + * Parse a {@link String} to a {@link com.mongodb.ConnectionString}. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ConnectionStringPropertyEditor extends PropertyEditorSupport { + + /* + * (non-Javadoc) + * @see java.beans.PropertyEditorSupport#setAsText(java.lang.String) + */ + @Override + public void setAsText(@Nullable String connectionString) { + + if (!StringUtils.hasText(connectionString)) { + return; + } + + setValue(new ConnectionString(connectionString)); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java index 8aa0a04887..b6e13d8568 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java @@ -50,10 +50,11 @@ public BeanDefinition parse(Element element, ParserContext parserContext) { ParsingUtils.setPropertyValue(builder, element, "port", "port"); ParsingUtils.setPropertyValue(builder, element, "host", "host"); - ParsingUtils.setPropertyValue(builder, element, "credentials", "credentials"); + ParsingUtils.setPropertyValue(builder, element, "credential", "credential"); + ParsingUtils.setPropertyValue(builder, element, "replica-set", "replicaSet"); + ParsingUtils.setPropertyValue(builder, element, "connection-string", "connectionString"); - MongoParsingUtils.parseMongoClientOptions(element, builder); - MongoParsingUtils.parseReplicaSet(element, builder); + MongoParsingUtils.parseMongoClientSettings(element, builder); String defaultedId = StringUtils.hasText(id) ? id : BeanNames.MONGO_BEAN_NAME; @@ -62,20 +63,28 @@ public BeanDefinition parse(Element element, ParserContext parserContext) { BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId); parserContext.registerBeanComponent(mongoComponent); - BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(MongoParsingUtils - .getServerAddressPropertyEditorBuilder()); + BeanComponentDefinition connectionStringPropertyEditor = helper + .getComponent(MongoParsingUtils.getConnectionStringPropertyEditorBuilder()); + parserContext.registerBeanComponent(connectionStringPropertyEditor); + + BeanComponentDefinition serverAddressPropertyEditor = helper + .getComponent(MongoParsingUtils.getServerAddressPropertyEditorBuilder()); parserContext.registerBeanComponent(serverAddressPropertyEditor); - BeanComponentDefinition writeConcernEditor = helper.getComponent(MongoParsingUtils - .getWriteConcernPropertyEditorBuilder()); + BeanComponentDefinition writeConcernEditor = helper + .getComponent(MongoParsingUtils.getWriteConcernPropertyEditorBuilder()); parserContext.registerBeanComponent(writeConcernEditor); - BeanComponentDefinition readPreferenceEditor = helper.getComponent(MongoParsingUtils - .getReadPreferencePropertyEditorBuilder()); + BeanComponentDefinition readConcernEditor = helper + .getComponent(MongoParsingUtils.getReadConcernPropertyEditorBuilder()); + parserContext.registerBeanComponent(readConcernEditor); + + BeanComponentDefinition readPreferenceEditor = helper + .getComponent(MongoParsingUtils.getReadPreferencePropertyEditorBuilder()); parserContext.registerBeanComponent(readPreferenceEditor); - BeanComponentDefinition credentialsEditor = helper.getComponent(MongoParsingUtils - .getMongoCredentialPropertyEditor()); + BeanComponentDefinition credentialsEditor = helper + .getComponent(MongoParsingUtils.getMongoCredentialPropertyEditor()); parserContext.registerBeanComponent(credentialsEditor); parserContext.popAndRegisterContainingComponent(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java index 272b4f1638..677561c0d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java @@ -32,14 +32,12 @@ import org.springframework.beans.factory.xml.ParserContext; import org.springframework.data.config.BeanComponentDefinitionBuilder; import org.springframework.data.mongodb.core.MongoClientFactoryBean; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import org.w3c.dom.Element; -import com.mongodb.Mongo; -import com.mongodb.MongoClientURI; -import com.mongodb.MongoURI; +import com.mongodb.ConnectionString; /** * {@link BeanDefinitionParser} to parse {@code db-factory} elements into {@link BeanDefinition}s. @@ -84,10 +82,11 @@ protected String resolveId(Element element, AbstractBeanDefinition definition, P protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { // Common setup - BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class); + BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder + .genericBeanDefinition(SimpleMongoClientDbFactory.class); setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern"); - BeanDefinition mongoUri = getMongoUri(element, parserContext); + BeanDefinition mongoUri = getConnectionString(element, parserContext); if (mongoUri != null) { @@ -97,7 +96,8 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext); - String mongoRef = element.getAttribute("mongo-ref"); + String mongoRef = element.getAttribute("mongo-client-ref"); + String dbname = element.getAttribute("dbname"); // Defaulting @@ -119,8 +119,8 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa } /** - * Registers a default {@link BeanDefinition} of a {@link Mongo} instance and returns the name under which the - * {@link Mongo} instance was registered under. + * Registers a default {@link BeanDefinition} of a {@link com.mongodb.client.MongoClient} instance and returns the + * name under which the {@link com.mongodb.client.MongoClient} instance was registered under. * * @param element must not be {@literal null}. * @param parserContext must not be {@literal null}. @@ -136,8 +136,7 @@ private BeanDefinition registerMongoBeanDefinition(Element element, ParserContex } /** - * Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured - * attributes.
+ * Creates a {@link BeanDefinition} for a {@link ConnectionString} depending on configured attributes.
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except * {@literal write-concern} and/or {@literal id}. * @@ -146,11 +145,19 @@ private BeanDefinition registerMongoBeanDefinition(Element element, ParserContex * @return {@literal null} in case no client-/uri defined. */ @Nullable - private BeanDefinition getMongoUri(Element element, ParserContext parserContext) { + private BeanDefinition getConnectionString(Element element, ParserContext parserContext) { + + String type = null; - boolean hasClientUri = element.hasAttribute("client-uri"); + if (element.hasAttribute("client-uri")) { + type = "client-uri"; + } else if (element.hasAttribute("connection-string")) { + type = "connection-string"; + } else if (element.hasAttribute("uri")) { + type = "uri"; + } - if (!hasClientUri && !element.hasAttribute("uri")) { + if (!StringUtils.hasText(type)) { return null; } @@ -164,16 +171,12 @@ private BeanDefinition getMongoUri(Element element, ParserContext parserContext) if (element.getAttributes().getLength() > allowedAttributesCount) { - parserContext.getReaderContext().error( - "Configure either " + (hasClientUri ? "Mongo Client URI" : "Mongo URI") + " or details individually!", + parserContext.getReaderContext().error("Configure either MongoDB " + type + " or details individually!", parserContext.extractSource(element)); } - Class type = MongoClientURI.class; - String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri"); - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type); - builder.addConstructorArgValue(uri); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ConnectionString.class); + builder.addConstructorArgValue(element.getAttribute(type)); return builder.getBeanDefinition(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index aa85041d9e..96d6a23200 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean; +import org.springframework.data.mongodb.core.MongoClientSettingsFactoryBean; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -43,60 +43,77 @@ abstract class MongoParsingUtils { private MongoParsingUtils() {} /** - * Parses the mongo replica-set element. - * - * @param parserContext the parser context - * @param element the mongo element - * @param mongoBuilder the bean definition builder to populate - * @return - */ - static void parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) { - setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds"); - } - - /** - * Parses the {@code mongo:client-options} sub-element. Populates the given attribute factory with the proper + * Parses the {@code mongo:client-settings} sub-element. Populates the given attribute factory with the proper * attributes. - * - * @param element must not be {@literal null}. - * @param mongoClientBuilder must not be {@literal null}. + * + * @param element + * @param mongoClientBuilder * @return - * @since 1.7 + * @since 3.0 */ - public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) { + public static boolean parseMongoClientSettings(Element element, BeanDefinitionBuilder mongoClientBuilder) { - Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options"); - - if (optionsElement == null) { + Element settingsElement = DomUtils.getChildElementByTagName(element, "client-settings"); + if (settingsElement == null) { return false; } BeanDefinitionBuilder clientOptionsDefBuilder = BeanDefinitionBuilder - .genericBeanDefinition(MongoClientOptionsFactoryBean.class); - - setPropertyValue(clientOptionsDefBuilder, optionsElement, "description", "description"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-connections-per-host", "minConnectionsPerHost"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier", - "threadsAllowedToBlockForConnectionMultiplier"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-idle-time", "maxConnectionIdleTime"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-life-time", "maxConnectionLifeTime"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "read-preference", "readPreference"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "write-concern", "writeConcern"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-frequency", "heartbeatFrequency"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-heartbeat-frequency", "minHeartbeatFrequency"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-connect-timeout", "heartbeatConnectTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-socket-timeout", "heartbeatSocketTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "ssl", "ssl"); - setPropertyReference(clientOptionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory"); - setPropertyReference(clientOptionsDefBuilder, optionsElement, "encryption-settings-ref", "autoEncryptionSettings"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "server-selection-timeout", "serverSelectionTimeout"); - - mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition()); + .genericBeanDefinition(MongoClientSettingsFactoryBean.class); + + setPropertyValue(clientOptionsDefBuilder, settingsElement, "application-name", "applicationName"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "read-preference", "readPreference"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "read-concern", "readConcern"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "write-concern", "writeConcern"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "retry-reads", "retryReads"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "retry-writes", "retryWrites"); + + // SocketSettings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-connect-timeout", "socketConnectTimeoutMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-read-timeout", "socketReadTimeoutMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-receive-buffer-size", "socketReceiveBufferSize"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-send-buffer-size", "socketSendBufferSize"); + + // Server Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "server-heartbeat-frequency", + "serverHeartbeatFrequencyMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "server-min-heartbeat-frequency", + "serverMinHeartbeatFrequencyMS"); + + // Cluster Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-srv-host", "clusterSrvHost"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-hosts", "clusterHosts"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-connection-mode", "clusterConnectionMode"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-type", "custerRequiredClusterType"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-local-threshold", "clusterLocalThresholdMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-server-selection-timeout", + "clusterServerSelectionTimeoutMS"); + + // Connection Pool Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-size", "poolMaxSize"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-min-size", "poolMinSize"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-wait-time", "poolMaxWaitTimeMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-connection-life-time", + "poolMaxConnectionLifeTimeMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-connection-idle-time", + "poolMaxConnectionIdleTimeMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-maintenance-initial-delay", + "poolMaintenanceInitialDelayMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-maintenance-frequency", + "poolMaintenanceFrequencyMS"); + + // SSL Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "ssl-enabled", "sslEnabled"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "ssl-invalid-host-name-allowed", + "sslInvalidHostNameAllowed"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "ssl-provider", "sslProvider"); + + // Field level encryption + setPropertyReference(clientOptionsDefBuilder, settingsElement, "encryption-settings-ref", "autoEncryptionSettings"); + + // and the rest + + mongoClientBuilder.addPropertyValue("mongoClientSettings", clientOptionsDefBuilder.getBeanDefinition()); return true; } @@ -118,6 +135,24 @@ static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() { return builder; } + /** + * Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a + * {@link ReadConcernPropertyEditor}. + * + * @return + * @since 3.0 + */ + static BeanDefinitionBuilder getReadConcernPropertyEditorBuilder() { + + Map> customEditors = new ManagedMap<>(); + customEditors.put("com.mongodb.ReadConcern", ReadConcernPropertyEditor.class); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); + builder.addPropertyValue("customEditors", customEditors); + + return builder; + } + /** * One should only register one bean definition but want to have the convenience of using * AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the @@ -125,7 +160,7 @@ static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() { */ static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() { - Map customEditors = new ManagedMap(); + Map customEditors = new ManagedMap<>(); customEditors.put("com.mongodb.ServerAddress[]", "org.springframework.data.mongodb.config.ServerAddressPropertyEditor"); @@ -143,7 +178,7 @@ static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() { */ static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() { - Map> customEditors = new ManagedMap>(); + Map> customEditors = new ManagedMap<>(); customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); @@ -169,4 +204,23 @@ static BeanDefinitionBuilder getMongoCredentialPropertyEditor() { return builder; } + + /** + * Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a + * {@link ConnectionStringPropertyEditor}. + * + * @return + * @since 3.0 + */ + static BeanDefinitionBuilder getConnectionStringPropertyEditorBuilder() { + + Map> customEditors = new ManagedMap<>(); + customEditors.put("com.mongodb.ConnectionString", ConnectionStringPropertyEditor.class); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); + builder.addPropertyValue("customEditors", customEditors); + + return builder; + } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java new file mode 100644 index 0000000000..ed5d73d6e6 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 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 + * + * https://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.config; + +import java.beans.PropertyEditorSupport; + +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import com.mongodb.ReadConcern; +import com.mongodb.ReadConcernLevel; + +/** + * Parse a {@link String} to a {@link ReadConcern}. If it is a well know {@link String} as identified by the + * {@link ReadConcernLevel#fromString(String)}. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ReadConcernPropertyEditor extends PropertyEditorSupport { + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext) + */ + @Override + public void setAsText(@Nullable String readConcernString) { + + if (!StringUtils.hasText(readConcernString)) { + return; + } + + setValue(new ReadConcern(ReadConcernLevel.fromString(readConcernString))); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java index 0ce3f00012..e1b1531e15 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java @@ -34,7 +34,7 @@ public class WriteConcernPropertyEditor extends PropertyEditorSupport { /** - * Parse a string to a List + * Parse a string to a {@link WriteConcern}. */ @Override public void setAsText(@Nullable String writeConcernString) { @@ -51,6 +51,5 @@ public void setAsText(@Nullable String writeConcernString) { // pass on the string to the constructor setValue(new WriteConcern(writeConcernString)); } - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java index 8a92d39e5d..e198368927 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.util.Assert; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; /** @@ -34,24 +34,13 @@ @ManagedResource(description = "Mongo Admin Operations") public class MongoAdmin implements MongoAdminOperations { - private final Object mongoClient; - - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link MongoAdmin#MongoAdmin(com.mongodb.client.MongoClient)}. - */ - @Deprecated - public MongoAdmin(MongoClient mongoClient) { - - Assert.notNull(mongoClient, "MongoClient must not be null!"); - this.mongoClient = mongoClient; - } + private final MongoClient mongoClient; /** * @param client the underlying {@link com.mongodb.client.MongoClient} used for data access. * @since 2.2 */ - public MongoAdmin(com.mongodb.client.MongoClient client) { + public MongoAdmin(MongoClient client) { Assert.notNull(client, "Client must not be null!"); this.mongoClient = client; @@ -88,11 +77,6 @@ public String getServerStatus() { } MongoDatabase getDB(String databaseName) { - - if (mongoClient instanceof MongoClient) { - return ((MongoClient) mongoClient).getDatabase(databaseName); - } - - return ((com.mongodb.client.MongoClient) mongoClient).getDatabase(databaseName); + return mongoClient.getDatabase(databaseName); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index 3f207eba02..e103fd37fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -16,70 +16,70 @@ package org.springframework.data.mongodb.core; import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.connection.ClusterSettings; +import com.mongodb.connection.ConnectionPoolSettings; +import com.mongodb.connection.ServerSettings; +import com.mongodb.connection.SocketSettings; +import com.mongodb.connection.SslSettings; +import com.mongodb.event.ClusterListener; /** * Convenient factory for configuring MongoDB. * * @author Christoph Strobl * @author Mark Paluch - * @since 1.7 - * @deprecated since 2.2 - There is no replacement for this {@link org.springframework.beans.factory.FactoryBean} at - * this time. However moving forward the {@link org.springframework.beans.factory.FactoryBean} will be - * suitable to provide instances of {@link com.mongodb.client.MongoClient}. */ -@Deprecated public class MongoClientFactoryBean extends AbstractFactoryBean implements PersistenceExceptionTranslator { private static final PersistenceExceptionTranslator DEFAULT_EXCEPTION_TRANSLATOR = new MongoExceptionTranslator(); - private @Nullable MongoClientOptions mongoClientOptions; + private @Nullable MongoClientSettings mongoClientSettings; private @Nullable String host; private @Nullable Integer port; - private List replicaSetSeeds = Collections.emptyList(); - private List credentials = Collections.emptyList(); + private @Nullable List credential = null; + private @Nullable ConnectionString connectionString; + private @Nullable String replicaSet = null; private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_EXCEPTION_TRANSLATOR; /** - * Set the {@link MongoClientOptions} to be used when creating {@link MongoClient}. + * Set the {@link MongoClientSettings} to be used when creating {@link MongoClient}. * * @param mongoClientOptions */ - public void setMongoClientOptions(@Nullable MongoClientOptions mongoClientOptions) { - this.mongoClientOptions = mongoClientOptions; + public void setMongoClientSettings(@Nullable MongoClientSettings mongoClientOptions) { + this.mongoClientSettings = mongoClientOptions; } /** * Set the list of credentials to be used when creating {@link MongoClient}. * - * @param credentials can be {@literal null}. + * @param credential can be {@literal null}. */ - public void setCredentials(@Nullable MongoCredential[] credentials) { - this.credentials = filterNonNullElementsAsList(credentials); - } - - /** - * Set the list of {@link ServerAddress} to build up a replica set for. - * - * @param replicaSetSeeds can be {@literal null}. - */ - public void setReplicaSetSeeds(@Nullable ServerAddress[] replicaSetSeeds) { - this.replicaSetSeeds = filterNonNullElementsAsList(replicaSetSeeds); + public void setCredential(@Nullable MongoCredential[] credential) { + this.credential = Arrays.asList(credential); } /** @@ -100,6 +100,14 @@ public void setPort(int port) { this.port = port; } + public void setConnectionString(@Nullable ConnectionString connectionString) { + this.connectionString = connectionString; + } + + public void setReplicaSet(@Nullable String replicaSet) { + this.replicaSet = replicaSet; + } + /** * Configures the {@link PersistenceExceptionTranslator} to use. * @@ -132,63 +140,212 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) { */ @Override protected MongoClient createInstance() throws Exception { + return createMongoClient(computeClientSetting()); + } + + /** + * Create {@link MongoClientSettings} based on configuration and priority (lower is better).
+ * 1. {@link MongoClientFactoryBean#mongoClientSettings}
+ * 2. {@link MongoClientFactoryBean#connectionString}
+ * 3. default {@link MongoClientSettings} + * + * @since 3.0 + */ + protected MongoClientSettings computeClientSetting() { - if (mongoClientOptions == null) { - mongoClientOptions = MongoClientOptions.builder().build(); + if (connectionString != null && (StringUtils.hasText(host) || port != null)) { + throw new IllegalStateException("ConnectionString and host/port configuration exclude one another!"); } - return createMongoClient(); - } + ConnectionString connectionString = this.connectionString != null ? this.connectionString + : new ConnectionString(String.format("mongodb://%s:%s", getOrDefault(host, ServerAddress.defaultHost()), + getOrDefault(port, "" + ServerAddress.defaultPort()))); - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.AbstractFactoryBean#destroyInstance(java.lang.Object) - */ - @Override - protected void destroyInstance(@Nullable MongoClient instance) throws Exception { + Builder builder = MongoClientSettings.builder().applyConnectionString(connectionString); - if (instance != null) { - instance.close(); + if (mongoClientSettings != null) { + + MongoClientSettings defaultSettings = MongoClientSettings.builder().build(); + + SslSettings sslSettings = mongoClientSettings.getSslSettings(); + ClusterSettings clusterSettings = mongoClientSettings.getClusterSettings(); + ConnectionPoolSettings connectionPoolSettings = mongoClientSettings.getConnectionPoolSettings(); + SocketSettings socketSettings = mongoClientSettings.getSocketSettings(); + ServerSettings serverSettings = mongoClientSettings.getServerSettings(); + + builder = builder // + .applicationName(computeSettingsValue(defaultSettings.getApplicationName(), + mongoClientSettings.getApplicationName(), connectionString.getApplicationName())) // + .applyToSslSettings(settings -> { + + applySettings(settings::enabled, computeSettingsValue(SslSettings::isEnabled, + defaultSettings.getSslSettings(), sslSettings, connectionString.getSslEnabled())); + applySettings(settings::invalidHostNameAllowed, (computeSettingsValue(SslSettings::isInvalidHostNameAllowed, + defaultSettings.getSslSettings(), sslSettings, connectionString.getSslInvalidHostnameAllowed()))); + settings.context(sslSettings.getContext()); + }).applyToClusterSettings(settings -> { + + applySettings(settings::hosts, + computeSettingsValue(ClusterSettings::getHosts, defaultSettings.getClusterSettings(), clusterSettings, + connectionString.getHosts().stream().map(ServerAddress::new).collect(Collectors.toList()))); + + applySettings(settings::requiredReplicaSetName, + computeSettingsValue(ClusterSettings::getRequiredReplicaSetName, defaultSettings.getClusterSettings(), + clusterSettings, connectionString.getRequiredReplicaSetName())); + + applySettings(settings::srvHost, computeSettingsValue(ClusterSettings::getSrvHost, + defaultSettings.getClusterSettings(), clusterSettings, null)); + + applySettings(settings::mode, computeSettingsValue(ClusterSettings::getMode, + defaultSettings.getClusterSettings(), clusterSettings, null)); + + applySettings(it -> settings.localThreshold(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ClusterSettings it) -> it.getLocalThreshold(TimeUnit.MILLISECONDS), + defaultSettings.getClusterSettings(), clusterSettings, connectionString.getLocalThreshold())); + + applySettings(settings::requiredClusterType, computeSettingsValue(ClusterSettings::getRequiredClusterType, + defaultSettings.getClusterSettings(), clusterSettings, null)); + applySettings(it -> settings.serverSelectionTimeout(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ClusterSettings it) -> it.getServerSelectionTimeout(TimeUnit.MILLISECONDS), + defaultSettings.getClusterSettings(), clusterSettings, + connectionString.getServerSelectionTimeout())); + + applySettings(settings::serverSelector, computeSettingsValue(ClusterSettings::getServerSelector, + defaultSettings.getClusterSettings(), clusterSettings, null)); + List clusterListeners = computeSettingsValue(ClusterSettings::getClusterListeners, + defaultSettings.getClusterSettings(), clusterSettings, null); + if (clusterListeners != null) { + clusterListeners.forEach(settings::addClusterListener); + } + }) // + .applyToConnectionPoolSettings(settings -> { + + applySettings(it -> settings.maintenanceFrequency(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaintenanceFrequency(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); + + applySettings(it -> settings.maxConnectionIdleTime(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaxConnectionIdleTime(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, + connectionString.getMaxConnectionIdleTime())); + + applySettings(it -> settings.maxConnectionLifeTime(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaxConnectionLifeTime(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, + connectionString.getMaxConnectionLifeTime())); + + applySettings(it -> settings.maxWaitTime(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaxWaitTime(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, + connectionString.getMaxWaitTime())); + + applySettings(it -> settings.maintenanceInitialDelay(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue( + (ConnectionPoolSettings it) -> it.getMaintenanceInitialDelay(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); + + applySettings(settings::minSize, + computeSettingsValue(ConnectionPoolSettings::getMinSize, defaultSettings.getConnectionPoolSettings(), + connectionPoolSettings, connectionString.getMinConnectionPoolSize())); + applySettings(settings::maxSize, + computeSettingsValue(ConnectionPoolSettings::getMaxSize, defaultSettings.getConnectionPoolSettings(), + connectionPoolSettings, connectionString.getMaxConnectionPoolSize())); + }) // + .applyToSocketSettings(settings -> { + + applySettings(it -> settings.connectTimeout(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((SocketSettings it) -> it.getConnectTimeout(TimeUnit.MILLISECONDS), + defaultSettings.getSocketSettings(), socketSettings, connectionString.getConnectTimeout())); + + applySettings(it -> settings.readTimeout(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((SocketSettings it) -> it.getReadTimeout(TimeUnit.MILLISECONDS), + defaultSettings.getSocketSettings(), socketSettings, connectionString.getSocketTimeout())); + applySettings(settings::receiveBufferSize, computeSettingsValue(SocketSettings::getReceiveBufferSize, + defaultSettings.getSocketSettings(), socketSettings, null)); + applySettings(settings::sendBufferSize, computeSettingsValue(SocketSettings::getSendBufferSize, + defaultSettings.getSocketSettings(), socketSettings, null)); + }) // + .applyToServerSettings(settings -> { + + applySettings(it -> settings.minHeartbeatFrequency(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ServerSettings it) -> it.getMinHeartbeatFrequency(TimeUnit.MILLISECONDS), + defaultSettings.getServerSettings(), serverSettings, null)); + + applySettings(it -> settings.heartbeatFrequency(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ServerSettings it) -> it.getHeartbeatFrequency(TimeUnit.MILLISECONDS), + defaultSettings.getServerSettings(), serverSettings, connectionString.getHeartbeatFrequency())); + settings.applySettings(serverSettings); + }) // + .autoEncryptionSettings(mongoClientSettings.getAutoEncryptionSettings()) // + .codecRegistry(mongoClientSettings.getCodecRegistry()); // + + applySettings(builder::readConcern, computeSettingsValue(defaultSettings.getReadConcern(), + mongoClientSettings.getReadConcern(), connectionString.getReadConcern())); + applySettings(builder::writeConcern, computeSettingsValue(defaultSettings.getWriteConcern(), + mongoClientSettings.getWriteConcern(), connectionString.getWriteConcern())); + applySettings(builder::readPreference, computeSettingsValue(defaultSettings.getReadPreference(), + mongoClientSettings.getReadPreference(), connectionString.getReadPreference())); + applySettings(builder::retryReads, computeSettingsValue(defaultSettings.getRetryReads(), + mongoClientSettings.getRetryReads(), connectionString.getRetryReads())); + applySettings(builder::retryWrites, computeSettingsValue(defaultSettings.getRetryWrites(), + mongoClientSettings.getRetryWrites(), connectionString.getRetryWritesValue())); } - } - private MongoClient createMongoClient() throws UnknownHostException { + if (!CollectionUtils.isEmpty(credential)) { + builder = builder.credential(credential.iterator().next()); + } - if (!CollectionUtils.isEmpty(replicaSetSeeds)) { - return new MongoClient(replicaSetSeeds, credentials, mongoClientOptions); + if (StringUtils.hasText(replicaSet)) { + builder.applyToClusterSettings((settings) -> { + settings.requiredReplicaSetName(replicaSet); + }); } - return new MongoClient(createConfiguredOrDefaultServerAddress(), credentials, mongoClientOptions); + return builder.build(); } - private ServerAddress createConfiguredOrDefaultServerAddress() throws UnknownHostException { + private void applySettings(Consumer settingsBuilder, @Nullable T value) { - ServerAddress defaultAddress = new ServerAddress(); + if (ObjectUtils.isEmpty(value)) { + return; + } + settingsBuilder.accept(value); + } - return new ServerAddress(StringUtils.hasText(host) ? host : defaultAddress.getHost(), - port != null ? port.intValue() : defaultAddress.getPort()); + private T computeSettingsValue(Function function, S defaultValueHolder, S settingsValueHolder, + @Nullable T connectionStringValue) { + return computeSettingsValue(function.apply(defaultValueHolder), function.apply(settingsValueHolder), + connectionStringValue); } - /** - * Returns the given array as {@link List} with all {@literal null} elements removed. - * - * @param elements the elements to filter , can be {@literal null}. - * @return a new unmodifiable {@link List#} from the given elements without {@literal null}s. - */ - private static List filterNonNullElementsAsList(@Nullable T[] elements) { + private T computeSettingsValue(T defaultValue, T fromSettings, T fromConnectionString) { + + boolean fromSettingsIsDefault = ObjectUtils.nullSafeEquals(defaultValue, fromSettings); + boolean fromConnectionStringIsDefault = ObjectUtils.nullSafeEquals(defaultValue, fromConnectionString); - if (elements == null) { - return Collections.emptyList(); + if (!fromSettingsIsDefault) { + return fromSettings; } + return !fromConnectionStringIsDefault ? fromConnectionString : defaultValue; + } - List candidateElements = new ArrayList(); + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.config.AbstractFactoryBean#destroyInstance(java.lang.Object) + */ + @Override + protected void destroyInstance(@Nullable MongoClient instance) throws Exception { - for (T element : elements) { - if (element != null) { - candidateElements.add(element); - } + if (instance != null) { + instance.close(); } + } + + private MongoClient createMongoClient(MongoClientSettings settings) throws UnknownHostException { + return MongoClients.create(settings); + } - return Collections.unmodifiableList(candidateElements); + private String getOrDefault(Object value, String defaultValue) { + return !StringUtils.isEmpty(value) ? value.toString() : defaultValue; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java deleted file mode 100644 index 8b2b552c7a..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2015-2020 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 - * - * https://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 javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; - -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.lang.Nullable; - -import com.mongodb.AutoEncryptionSettings; -import com.mongodb.DBDecoderFactory; -import com.mongodb.DBEncoderFactory; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; -import com.mongodb.ReadPreference; -import com.mongodb.WriteConcern; - -/** - * A factory bean for construction of a {@link MongoClientOptions} instance. - * - * @author Christoph Strobl - * @author Oliver Gierke - * @author Mark Paluch - * @since 1.7 - * @deprecated since 2.2 - There is no replacement for this {@link org.springframework.beans.factory.FactoryBean}. - * However moving forward there will be a dedicated factory bean for {@link com.mongodb.MongoClientSettings} - * replacing {@link MongoClientOptions}. - */ -@Deprecated -public class MongoClientOptionsFactoryBean extends AbstractFactoryBean { - - private static final MongoClientOptions DEFAULT_MONGO_OPTIONS = MongoClientOptions.builder().build(); - - // TODO: Mongo Driver 4 - use application name insetad of description if not available - private @Nullable String description = DEFAULT_MONGO_OPTIONS.getApplicationName(); - private int minConnectionsPerHost = DEFAULT_MONGO_OPTIONS.getMinConnectionsPerHost(); - private int connectionsPerHost = DEFAULT_MONGO_OPTIONS.getConnectionsPerHost(); - private int threadsAllowedToBlockForConnectionMultiplier = DEFAULT_MONGO_OPTIONS - .getThreadsAllowedToBlockForConnectionMultiplier(); - private int maxWaitTime = DEFAULT_MONGO_OPTIONS.getMaxWaitTime(); - private int maxConnectionIdleTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionIdleTime(); - private int maxConnectionLifeTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionLifeTime(); - private int connectTimeout = DEFAULT_MONGO_OPTIONS.getConnectTimeout(); - private int socketTimeout = DEFAULT_MONGO_OPTIONS.getSocketTimeout(); - - // TODO: Mongo Driver 4 - check if available - private boolean socketKeepAlive = DEFAULT_MONGO_OPTIONS.isSocketKeepAlive(); - private @Nullable ReadPreference readPreference = DEFAULT_MONGO_OPTIONS.getReadPreference(); - private DBDecoderFactory dbDecoderFactory = DEFAULT_MONGO_OPTIONS.getDbDecoderFactory(); - private DBEncoderFactory dbEncoderFactory = DEFAULT_MONGO_OPTIONS.getDbEncoderFactory(); - private @Nullable WriteConcern writeConcern = DEFAULT_MONGO_OPTIONS.getWriteConcern(); - private @Nullable SocketFactory socketFactory = DEFAULT_MONGO_OPTIONS.getSocketFactory(); - private boolean cursorFinalizerEnabled = DEFAULT_MONGO_OPTIONS.isCursorFinalizerEnabled(); - - // TODO: Mongo Driver 4 - remove this option - private boolean alwaysUseMBeans = DEFAULT_MONGO_OPTIONS.isAlwaysUseMBeans(); - private int heartbeatFrequency = DEFAULT_MONGO_OPTIONS.getHeartbeatFrequency(); - private int minHeartbeatFrequency = DEFAULT_MONGO_OPTIONS.getMinHeartbeatFrequency(); - private int heartbeatConnectTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatConnectTimeout(); - private int heartbeatSocketTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatSocketTimeout(); - private String requiredReplicaSetName = DEFAULT_MONGO_OPTIONS.getRequiredReplicaSetName(); - private int serverSelectionTimeout = DEFAULT_MONGO_OPTIONS.getServerSelectionTimeout(); - - private boolean ssl; - private @Nullable SSLSocketFactory sslSocketFactory; - private @Nullable AutoEncryptionSettings autoEncryptionSettings; - - /** - * Set the {@link MongoClient} description. - * - * @param description - */ - // TODO: Mongo Driver 4 - deprecate that one and add application name - public void setDescription(@Nullable String description) { - this.description = description; - } - - /** - * Set the minimum number of connections per host. - * - * @param minConnectionsPerHost - */ - public void setMinConnectionsPerHost(int minConnectionsPerHost) { - this.minConnectionsPerHost = minConnectionsPerHost; - } - - /** - * Set the number of connections allowed per host. Will block if run out. Default is 10. System property - * {@code MONGO.POOLSIZE} can override - * - * @param connectionsPerHost - */ - public void setConnectionsPerHost(int connectionsPerHost) { - this.connectionsPerHost = connectionsPerHost; - } - - /** - * Set the multiplier for connectionsPerHost for # of threads that can block. Default is 5. If connectionsPerHost is - * 10, and threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an - * exception will be thrown. - * - * @param threadsAllowedToBlockForConnectionMultiplier - */ - public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier) { - this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; - } - - /** - * Set the max wait time of a blocking thread for a connection. Default is 12000 ms (2 minutes) - * - * @param maxWaitTime - */ - public void setMaxWaitTime(int maxWaitTime) { - this.maxWaitTime = maxWaitTime; - } - - /** - * The maximum idle time for a pooled connection. - * - * @param maxConnectionIdleTime - */ - public void setMaxConnectionIdleTime(int maxConnectionIdleTime) { - this.maxConnectionIdleTime = maxConnectionIdleTime; - } - - /** - * Set the maximum life time for a pooled connection. - * - * @param maxConnectionLifeTime - */ - public void setMaxConnectionLifeTime(int maxConnectionLifeTime) { - this.maxConnectionLifeTime = maxConnectionLifeTime; - } - - /** - * Set the connect timeout in milliseconds. 0 is default and infinite. - * - * @param connectTimeout - */ - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } - - /** - * Set the socket timeout. 0 is default and infinite. - * - * @param socketTimeout - */ - public void setSocketTimeout(int socketTimeout) { - this.socketTimeout = socketTimeout; - } - - /** - * Set the keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. - * - * @param socketKeepAlive - */ - public void setSocketKeepAlive(boolean socketKeepAlive) { - this.socketKeepAlive = socketKeepAlive; - } - - /** - * Set the {@link ReadPreference}. - * - * @param readPreference - */ - public void setReadPreference(@Nullable ReadPreference readPreference) { - this.readPreference = readPreference; - } - - /** - * Set the {@link WriteConcern} that will be the default value used when asking the {@link MongoDbFactory} for a DB - * object. - * - * @param writeConcern - */ - public void setWriteConcern(@Nullable WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /** - * @param socketFactory - */ - public void setSocketFactory(@Nullable SocketFactory socketFactory) { - this.socketFactory = socketFactory; - } - - /** - * Set the frequency that the driver will attempt to determine the current state of each server in the cluster. - * - * @param heartbeatFrequency - */ - public void setHeartbeatFrequency(int heartbeatFrequency) { - this.heartbeatFrequency = heartbeatFrequency; - } - - /** - * In the event that the driver has to frequently re-check a server's availability, it will wait at least this long - * since the previous check to avoid wasted effort. - * - * @param minHeartbeatFrequency - */ - public void setMinHeartbeatFrequency(int minHeartbeatFrequency) { - this.minHeartbeatFrequency = minHeartbeatFrequency; - } - - /** - * Set the connect timeout for connections used for the cluster heartbeat. - * - * @param heartbeatConnectTimeout - */ - public void setHeartbeatConnectTimeout(int heartbeatConnectTimeout) { - this.heartbeatConnectTimeout = heartbeatConnectTimeout; - } - - /** - * Set the socket timeout for connections used for the cluster heartbeat. - * - * @param heartbeatSocketTimeout - */ - public void setHeartbeatSocketTimeout(int heartbeatSocketTimeout) { - this.heartbeatSocketTimeout = heartbeatSocketTimeout; - } - - /** - * Configures the name of the replica set. - * - * @param requiredReplicaSetName - */ - public void setRequiredReplicaSetName(String requiredReplicaSetName) { - this.requiredReplicaSetName = requiredReplicaSetName; - } - - /** - * This controls if the driver should us an SSL connection. Defaults to {@literal false}. - * - * @param ssl - */ - public void setSsl(boolean ssl) { - this.ssl = ssl; - } - - /** - * Set the {@link SSLSocketFactory} to use for the {@literal SSL} connection. If none is configured here, - * {@link SSLSocketFactory#getDefault()} will be used. - * - * @param sslSocketFactory - */ - public void setSslSocketFactory(@Nullable SSLSocketFactory sslSocketFactory) { - - this.sslSocketFactory = sslSocketFactory; - this.ssl = sslSocketFactory != null; - } - - /** - * Set the {@literal server selection timeout} in msec for a 3.x MongoDB Java driver. If not set the default value of - * 30 sec will be used. A value of 0 means that it will timeout immediately if no server is available. A negative - * value means to wait indefinitely. - * - * @param serverSelectionTimeout in msec. - */ - public void setServerSelectionTimeout(int serverSelectionTimeout) { - this.serverSelectionTimeout = serverSelectionTimeout; - } - - /** - * Set the {@link AutoEncryptionSettings} to be used. - * - * @param autoEncryptionSettings can be {@literal null}. - * @since 2.2 - */ - public void setAutoEncryptionSettings(@Nullable AutoEncryptionSettings autoEncryptionSettings) { - this.autoEncryptionSettings = autoEncryptionSettings; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance() - */ - @SuppressWarnings("ConstantConditions") - @Override - protected MongoClientOptions createInstance() throws Exception { - - SocketFactory socketFactoryToUse = ssl - ? (sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault()) - : this.socketFactory; - - return MongoClientOptions.builder() // - .alwaysUseMBeans(this.alwaysUseMBeans) // - .connectionsPerHost(this.connectionsPerHost) // - .connectTimeout(connectTimeout) // - .cursorFinalizerEnabled(cursorFinalizerEnabled) // - .dbDecoderFactory(dbDecoderFactory) // - .dbEncoderFactory(dbEncoderFactory) // - .applicationName(description) // TODO: Mongo Driver 4 - use application name if description not available - .heartbeatConnectTimeout(heartbeatConnectTimeout) // - .heartbeatFrequency(heartbeatFrequency) // - .heartbeatSocketTimeout(heartbeatSocketTimeout) // - .maxConnectionIdleTime(maxConnectionIdleTime) // - .maxConnectionLifeTime(maxConnectionLifeTime) // - .maxWaitTime(maxWaitTime) // - .minConnectionsPerHost(minConnectionsPerHost) // - .minHeartbeatFrequency(minHeartbeatFrequency) // - .readPreference(readPreference) // - .requiredReplicaSetName(requiredReplicaSetName) // - .serverSelectionTimeout(serverSelectionTimeout) // - .sslEnabled(ssl) // - .autoEncryptionSettings(autoEncryptionSettings) // - .socketFactory(socketFactoryToUse) // TODO: Mongo Driver 4 - - .socketKeepAlive(socketKeepAlive) // TODO: Mongo Driver 4 - remove if not available - .socketTimeout(socketTimeout) // - .threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier) // - .writeConcern(writeConcern).build(); - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObjectType() - */ - public Class getObjectType() { - return MongoClientOptions.class; - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java new file mode 100644 index 0000000000..e688433b68 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java @@ -0,0 +1,464 @@ +/* + * Copyright 2019 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 + * + * https://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 java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLContext; + +import org.bson.codecs.configuration.CodecRegistry; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import com.mongodb.AutoEncryptionSettings; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; +import com.mongodb.ReadConcern; +import com.mongodb.ReadPreference; +import com.mongodb.ServerAddress; +import com.mongodb.WriteConcern; +import com.mongodb.connection.ClusterConnectionMode; +import com.mongodb.connection.ClusterType; +import com.mongodb.connection.StreamFactoryFactory; + +/** + * A factory bean for construction of a {@link MongoClientSettings} instance to be used with a MongoDB driver. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class MongoClientSettingsFactoryBean extends AbstractFactoryBean { + + private static final MongoClientSettings DEFAULT_MONGO_SETTINGS = MongoClientSettings.builder().build(); + + private CodecRegistry codecRegistry = DEFAULT_MONGO_SETTINGS.getCodecRegistry(); + private StreamFactoryFactory streamFactoryFactory = DEFAULT_MONGO_SETTINGS.getStreamFactoryFactory(); + + private ReadPreference readPreference = DEFAULT_MONGO_SETTINGS.getReadPreference(); + private ReadConcern readConcern = DEFAULT_MONGO_SETTINGS.getReadConcern(); + private @Nullable Boolean retryReads = null; + + private WriteConcern writeConcern = DEFAULT_MONGO_SETTINGS.getWriteConcern(); + private @Nullable Boolean retryWrites = null; + + private @Nullable String applicationName = null; + + // --> Socket Settings + + private Integer socketConnectTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() + .getConnectTimeout(TimeUnit.MILLISECONDS); + private Integer socketReadTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() + .getReadTimeout(TimeUnit.MILLISECONDS); + private Integer socketReceiveBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReceiveBufferSize(); + private Integer socketSendBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getSendBufferSize(); + + /** + * @param socketConnectTimeoutMS in msec + * @see com.mongodb.connection.SocketSettings.Builder#connectTimeout(int, TimeUnit) + */ + public void setSocketConnectTimeoutMS(Integer socketConnectTimeoutMS) { + this.socketConnectTimeoutMS = socketConnectTimeoutMS; + } + + /** + * @param socketReadTimeoutMS in msec + * @see com.mongodb.connection.SocketSettings.Builder#readTimeout(int, TimeUnit) + */ + public void setSocketReadTimeoutMS(Integer socketReadTimeoutMS) { + this.socketReadTimeoutMS = socketReadTimeoutMS; + } + + /** + * @param socketReceiveBufferSize + * @see com.mongodb.connection.SocketSettings.Builder#receiveBufferSize(int) + */ + public void setSocketReceiveBufferSize(Integer socketReceiveBufferSize) { + this.socketReceiveBufferSize = socketReceiveBufferSize; + } + + /** + * @param socketSendBufferSize + * @see com.mongodb.connection.SocketSettings.Builder#sendBufferSize(int) + */ + public void setSocketSendBufferSize(Integer socketSendBufferSize) { + this.socketSendBufferSize = socketSendBufferSize; + } + + // --> Server Settings + + private Long serverHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + .getHeartbeatFrequency(TimeUnit.MILLISECONDS); + private Long serverMinHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + .getMinHeartbeatFrequency(TimeUnit.MILLISECONDS); + + /** + * @param serverHeartbeatFrequencyMS in msec + * @see com.mongodb.connection.ServerSettings.Builder#heartbeatFrequency(long, TimeUnit) + */ + public void setServerHeartbeatFrequencyMS(Long serverHeartbeatFrequencyMS) { + this.serverHeartbeatFrequencyMS = serverHeartbeatFrequencyMS; + } + + /** + * @param serverMinHeartbeatFrequencyMS in msec + * @see com.mongodb.connection.ServerSettings.Builder#minHeartbeatFrequency(long, TimeUnit) + */ + public void setServerMinHeartbeatFrequencyMS(Long serverMinHeartbeatFrequencyMS) { + this.serverMinHeartbeatFrequencyMS = serverMinHeartbeatFrequencyMS; + } + + // --> Cluster Settings + + private @Nullable String clusterSrvHost = DEFAULT_MONGO_SETTINGS.getClusterSettings().getSrvHost(); + private List clusterHosts = Collections.emptyList(); + private @Nullable ClusterConnectionMode clusterConnectionMode = null; + private ClusterType custerRequiredClusterType = DEFAULT_MONGO_SETTINGS.getClusterSettings().getRequiredClusterType(); + private String clusterRequiredReplicaSetName = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getRequiredReplicaSetName(); + private long clusterLocalThresholdMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getLocalThreshold(TimeUnit.MILLISECONDS); + private long clusterServerSelectionTimeoutMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getServerSelectionTimeout(TimeUnit.MILLISECONDS); + + /** + * @param clusterSrvHost + * @see com.mongodb.connection.ClusterSettings.Builder#srvHost(String) + */ + public void setClusterSrvHost(String clusterSrvHost) { + this.clusterSrvHost = clusterSrvHost; + } + + /** + * @param clusterHosts + * @see com.mongodb.connection.ClusterSettings.Builder#hosts(List) + */ + public void setClusterHosts(ServerAddress[] clusterHosts) { + this.clusterHosts = Arrays.asList(clusterHosts); + } + + /** + * ???? + * + * @param clusterConnectionMode + * @see com.mongodb.connection.ClusterSettings.Builder#mode(ClusterConnectionMode) + */ + public void setClusterConnectionMode(ClusterConnectionMode clusterConnectionMode) { + this.clusterConnectionMode = clusterConnectionMode; + } + + /** + * @param custerRequiredClusterType + * @see com.mongodb.connection.ClusterSettings.Builder#requiredClusterType(ClusterType) + */ + public void setCusterRequiredClusterType(ClusterType custerRequiredClusterType) { + this.custerRequiredClusterType = custerRequiredClusterType; + } + + /** + * @param clusterRequiredReplicaSetName + * @see com.mongodb.connection.ClusterSettings.Builder#requiredReplicaSetName(String) + */ + public void setClusterRequiredReplicaSetName(String clusterRequiredReplicaSetName) { + this.clusterRequiredReplicaSetName = clusterRequiredReplicaSetName; + } + + /** + * @param clusterLocalThresholdMS in msec + * @see com.mongodb.connection.ClusterSettings.Builder#localThreshold(long, TimeUnit) + */ + public void setClusterLocalThresholdMS(long clusterLocalThresholdMS) { + this.clusterLocalThresholdMS = clusterLocalThresholdMS; + } + + /** + * @param clusterServerSelectionTimeoutMS in msec + * @see com.mongodb.connection.ClusterSettings.Builder#serverSelectionTimeout(long, TimeUnit) + */ + public void setClusterServerSelectionTimeoutMS(long clusterServerSelectionTimeoutMS) { + this.clusterServerSelectionTimeoutMS = clusterServerSelectionTimeoutMS; + } + + // --> ConnectionPoolSettings + + private Integer poolMaxSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMaxSize(); + private Integer poolMinSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMinSize(); + private Long poolMaxWaitTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxWaitTime(TimeUnit.MILLISECONDS); + private Long poolMaxConnectionLifeTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxConnectionLifeTime(TimeUnit.MILLISECONDS); + private Long poolMaxConnectionIdleTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxConnectionIdleTime(TimeUnit.MILLISECONDS); + private Long poolMaintenanceInitialDelayMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaintenanceInitialDelay(TimeUnit.MILLISECONDS); + private Long poolMaintenanceFrequencyMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaintenanceFrequency(TimeUnit.MILLISECONDS); + + /** + * @param poolMaxSize + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxSize(int) + */ + public void setPoolMaxSize(Integer poolMaxSize) { + this.poolMaxSize = poolMaxSize; + } + + /** + * @param poolMinSize + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#minSize(int) + */ + public void setPoolMinSize(Integer poolMinSize) { + this.poolMinSize = poolMinSize; + } + + /** + * @param poolMaxWaitTimeMS in mesec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxWaitTime(long, TimeUnit) + */ + public void setPoolMaxWaitTimeMS(Long poolMaxWaitTimeMS) { + this.poolMaxWaitTimeMS = poolMaxWaitTimeMS; + } + + /** + * @param poolMaxConnectionLifeTimeMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxConnectionLifeTime(long, TimeUnit) + */ + public void setPoolMaxConnectionLifeTimeMS(Long poolMaxConnectionLifeTimeMS) { + this.poolMaxConnectionLifeTimeMS = poolMaxConnectionLifeTimeMS; + } + + /** + * @param poolMaxConnectionIdleTimeMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxConnectionIdleTime(long, TimeUnit) + */ + public void setPoolMaxConnectionIdleTimeMS(Long poolMaxConnectionIdleTimeMS) { + this.poolMaxConnectionIdleTimeMS = poolMaxConnectionIdleTimeMS; + } + + /** + * @param poolMaintenanceInitialDelayMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maintenanceInitialDelay(long, TimeUnit) + */ + public void setPoolMaintenanceInitialDelayMS(Long poolMaintenanceInitialDelayMS) { + this.poolMaintenanceInitialDelayMS = poolMaintenanceInitialDelayMS; + } + + /** + * @param poolMaintenanceFrequencyMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maintenanceFrequency(long, TimeUnit) + */ + public void setPoolMaintenanceFrequencyMS(Long poolMaintenanceFrequencyMS) { + this.poolMaintenanceFrequencyMS = poolMaintenanceFrequencyMS; + } + + // --> SSL Settings + + private Boolean sslEnabled = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled(); + private Boolean sslInvalidHostNameAllowed = DEFAULT_MONGO_SETTINGS.getSslSettings().isInvalidHostNameAllowed(); + private String sslProvider = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled() + ? DEFAULT_MONGO_SETTINGS.getSslSettings().getContext().getProvider().getName() + : ""; + + /** + * @param sslEnabled + * @see com.mongodb.connection.SslSettings.Builder#enabled(boolean) + */ + public void setSslEnabled(Boolean sslEnabled) { + this.sslEnabled = sslEnabled; + } + + /** + * @param sslInvalidHostNameAllowed + * @see com.mongodb.connection.SslSettings.Builder#invalidHostNameAllowed(boolean) + */ + public void setSslInvalidHostNameAllowed(Boolean sslInvalidHostNameAllowed) { + this.sslInvalidHostNameAllowed = sslInvalidHostNameAllowed; + } + + /** + * @param sslProvider + * @see com.mongodb.connection.SslSettings.Builder#context(SSLContext) + * @see SSLContext#getInstance(String) + */ + public void setSslProvider(String sslProvider) { + this.sslProvider = sslProvider; + } + + // encryption and retry + + private @Nullable AutoEncryptionSettings autoEncryptionSettings; + + /** + * @param applicationName + * @see MongoClientSettings.Builder#applicationName(String) + */ + public void setApplicationName(@Nullable String applicationName) { + this.applicationName = applicationName; + } + + /** + * @param retryReads + * @see MongoClientSettings.Builder#retryReads(boolean) + */ + public void setRetryReads(@Nullable Boolean retryReads) { + this.retryReads = retryReads; + } + + /** + * @param readConcern + * @see MongoClientSettings.Builder#readConcern(ReadConcern) + */ + public void setReadConcern(ReadConcern readConcern) { + this.readConcern = readConcern; + } + + /** + * @param writeConcern + * @see MongoClientSettings.Builder#writeConcern(WriteConcern) + */ + public void setWriteConcern(WriteConcern writeConcern) { + this.writeConcern = writeConcern; + } + + /** + * @param retryWrites + * @see MongoClientSettings.Builder#retryWrites(boolean) + */ + public void setRetryWrites(@Nullable Boolean retryWrites) { + this.retryWrites = retryWrites; + } + + /** + * @param readPreference + * @see MongoClientSettings.Builder#readPreference(ReadPreference) + */ + public void setReadPreference(ReadPreference readPreference) { + this.readPreference = readPreference; + } + + /** + * @param streamFactoryFactory + * @see MongoClientSettings.Builder#streamFactoryFactory(StreamFactoryFactory) + */ + public void setStreamFactoryFactory(StreamFactoryFactory streamFactoryFactory) { + this.streamFactoryFactory = streamFactoryFactory; + } + + /** + * @param codecRegistry + * @see MongoClientSettings.Builder#codecRegistry(CodecRegistry) + */ + public void setCodecRegistry(CodecRegistry codecRegistry) { + this.codecRegistry = codecRegistry; + } + + /** + * @param autoEncryptionSettings can be {@literal null}. + * @see MongoClientSettings.Builder#autoEncryptionSettings(AutoEncryptionSettings) + */ + public void setAutoEncryptionSettings(@Nullable AutoEncryptionSettings autoEncryptionSettings) { + this.autoEncryptionSettings = autoEncryptionSettings; + } + + @Override + public Class getObjectType() { + return MongoClientSettings.class; + } + + @Override + protected MongoClientSettings createInstance() { + + Builder builder = MongoClientSettings.builder() // + .readPreference(readPreference) // + .writeConcern(writeConcern) // + .readConcern(readConcern) // + .codecRegistry(codecRegistry) // + .applicationName(applicationName) // + .autoEncryptionSettings(autoEncryptionSettings)// + .applyToClusterSettings((settings) -> { + + settings.serverSelectionTimeout(clusterServerSelectionTimeoutMS, TimeUnit.MILLISECONDS); + if(clusterConnectionMode != null) { + settings.mode(clusterConnectionMode); + } + settings.requiredReplicaSetName(clusterRequiredReplicaSetName); + + if (!CollectionUtils.isEmpty(clusterHosts)) { + settings.hosts(clusterHosts); + } + settings.localThreshold(clusterLocalThresholdMS, TimeUnit.MILLISECONDS); +// settings.maxWaitQueueSize(clusterMaxWaitQueueSize); + settings.requiredClusterType(custerRequiredClusterType); + + if (StringUtils.hasText(clusterSrvHost)) { + settings.srvHost(clusterSrvHost); + } + }) // + .applyToConnectionPoolSettings((settings) -> { + + settings.minSize(poolMinSize); + settings.maxSize(poolMaxSize); + settings.maxConnectionIdleTime(poolMaxConnectionIdleTimeMS, TimeUnit.MILLISECONDS); + settings.maxWaitTime(poolMaxWaitTimeMS, TimeUnit.MILLISECONDS); + settings.maxConnectionLifeTime(poolMaxConnectionLifeTimeMS, TimeUnit.MILLISECONDS); +// settings.maxWaitQueueSize(poolMaxWaitQueueSize); + settings.maintenanceFrequency(poolMaintenanceFrequencyMS, TimeUnit.MILLISECONDS); + settings.maintenanceInitialDelay(poolMaintenanceInitialDelayMS, TimeUnit.MILLISECONDS); + }) // + .applyToServerSettings((settings) -> { + + settings.minHeartbeatFrequency(serverMinHeartbeatFrequencyMS, TimeUnit.MILLISECONDS); + settings.heartbeatFrequency(serverHeartbeatFrequencyMS, TimeUnit.MILLISECONDS); + }) // + .applyToSocketSettings((settings) -> { + + settings.connectTimeout(socketConnectTimeoutMS.intValue(), TimeUnit.MILLISECONDS); + settings.readTimeout(socketReadTimeoutMS.intValue(), TimeUnit.MILLISECONDS); + settings.receiveBufferSize(socketReceiveBufferSize); + settings.sendBufferSize(socketSendBufferSize); + }) // + .applyToSslSettings((settings) -> { + + settings.enabled(sslEnabled); + if (ObjectUtils.nullSafeEquals(Boolean.TRUE, sslEnabled)) { + + settings.invalidHostNameAllowed(sslInvalidHostNameAllowed); + try { + settings.context(StringUtils.hasText(sslProvider) ? SSLContext.getInstance(sslProvider) : SSLContext.getDefault()); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + }); + + if (streamFactoryFactory != null) { + builder = builder.streamFactoryFactory(streamFactoryFactory); + } + if (retryReads != null) { + builder = builder.retryReads(retryReads); + } + if (retryWrites != null) { + builder = builder.retryWrites(retryWrites); + } + + return builder.build(); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java index 7451152203..f9cc9d5e8d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java @@ -16,10 +16,9 @@ package org.springframework.data.mongodb.core; import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.WriteResult; +import com.mongodb.WriteConcernResult; /** * Mongo-specific {@link DataIntegrityViolationException}. @@ -30,18 +29,18 @@ public class MongoDataIntegrityViolationException extends DataIntegrityViolation private static final long serialVersionUID = -186980521176764046L; - private final WriteResult writeResult; + private final WriteConcernResult writeResult; private final MongoActionOperation actionOperation; /** - * Creates a new {@link MongoDataIntegrityViolationException} using the given message and {@link WriteResult}. + * Creates a new {@link MongoDataIntegrityViolationException} using the given message and {@link WriteConcernResult}. * * @param message the exception message - * @param writeResult the {@link WriteResult} that causes the exception, must not be {@literal null}. + * @param writeResult the {@link WriteConcernResult} that causes the exception, must not be {@literal null}. * @param actionOperation the {@link MongoActionOperation} that caused the exception, must not be {@literal null}. */ - public MongoDataIntegrityViolationException(String message, WriteResult writeResult, - MongoActionOperation actionOperation) { + public MongoDataIntegrityViolationException(String message, WriteConcernResult writeResult, + MongoActionOperation actionOperation) { super(message); @@ -53,11 +52,11 @@ public MongoDataIntegrityViolationException(String message, WriteResult writeRes } /** - * Returns the {@link WriteResult} that caused the exception. + * Returns the {@link WriteConcernResult} that caused the exception. * * @return the writeResult */ - public WriteResult getWriteResult() { + public WriteConcernResult getWriteResult() { return writeResult; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index 9915656b5d..b14518b108 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -26,15 +26,14 @@ import org.springframework.util.Assert; import com.mongodb.ClientSessionOptions; -import com.mongodb.DB; import com.mongodb.WriteConcern; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; /** - * Common base class for usage with both {@link com.mongodb.client.MongoClients} and {@link com.mongodb.MongoClient} - * defining common properties such as database name and exception translator. + * Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as + * database name and exception translator. *

* Not intended to be used directly. * @@ -42,7 +41,6 @@ * @author Mark Paluch * @param Client type. * @since 2.1 - * @see SimpleMongoDbFactory * @see SimpleMongoClientDbFactory */ public abstract class MongoDbFactorySupport implements MongoDbFactory { @@ -89,18 +87,18 @@ public void setWriteConcern(WriteConcern writeConcern) { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb() + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() */ - public MongoDatabase getDb() throws DataAccessException { - return getDb(databaseName); + public MongoDatabase getMongoDatabase() throws DataAccessException { + return getMongoDatabase(getDefaultDatabaseName()); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) */ @Override - public MongoDatabase getDb(String dbName) throws DataAccessException { + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { Assert.hasText(dbName, "Database name must not be empty!"); @@ -181,20 +179,20 @@ static class ClientSessionBoundMongoDbFactory implements MongoDbFactory { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb() + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() */ @Override - public MongoDatabase getDb() throws DataAccessException { - return proxyMongoDatabase(delegate.getDb()); + public MongoDatabase getMongoDatabase() throws DataAccessException { + return proxyMongoDatabase(delegate.getMongoDatabase()); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) */ @Override - public MongoDatabase getDb(String dbName) throws DataAccessException { - return proxyMongoDatabase(delegate.getDb(dbName)); + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { + return proxyMongoDatabase(delegate.getMongoDatabase(dbName)); } /* @@ -206,15 +204,6 @@ public PersistenceExceptionTranslator getExceptionTranslator() { return delegate.getExceptionTranslator(); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getLegacyDb() - */ - @Override - public DB getLegacyDb() { - return delegate.getLegacyDb(); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index e06e83f61a..20199306f2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -29,7 +29,6 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.dao.PermissionDeniedDataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.data.mongodb.UncategorizedMongoDbException; @@ -37,7 +36,6 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; -import com.mongodb.BulkWriteException; import com.mongodb.MongoBulkWriteException; import com.mongodb.MongoException; import com.mongodb.MongoServerException; @@ -112,10 +110,6 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) { return new DataIntegrityViolationException(ex.getMessage(), ex); } - if (ex instanceof BulkWriteException) { - return new BulkOperationException(ex.getMessage(), (BulkWriteException) ex); - } - // All other MongoExceptions if (ex instanceof MongoException) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 635ec96d94..0ec065c2d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -48,7 +48,6 @@ import org.springframework.util.ClassUtils; import com.mongodb.ClientSessionOptions; -import com.mongodb.Cursor; import com.mongodb.ReadPreference; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoCollection; @@ -224,9 +223,10 @@ public T execute(SessionCallback action, Consumer onComple /** * Executes the given {@link Query} on the entity collection of the specified {@code entityType} backed by a Mongo DB - * {@link Cursor}. + * {@link com.mongodb.client.FindIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to + * be closed. * * @param query the query class that specifies the criteria used to find a record and also an optional fields * specification. Must not be {@literal null}. @@ -239,9 +239,10 @@ public T execute(SessionCallback action, Consumer onComple /** * Executes the given {@link Query} on the entity collection of the specified {@code entityType} and collection backed - * by a Mongo DB {@link Cursor}. + * by a Mongo DB {@link com.mongodb.client.FindIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to + * be closed. * * @param query the query class that specifies the criteria used to find a record and also an optional fields * specification. Must not be {@literal null}. @@ -360,7 +361,7 @@ public T execute(SessionCallback action, Consumer onComple IndexOperations indexOps(Class entityClass); /** - * Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.DB} level. + * Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.client.MongoDatabase} level. * * @return * @since 1.7 @@ -518,11 +519,11 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN AggregationResults aggregate(Aggregation aggregation, String collectionName, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class. The name of the inputCollection is derived from the inputType of - * the aggregation. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class. The name of the inputCollection is + * derived from the inputType of the aggregation. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -537,11 +538,11 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN CloseableIterator aggregateStream(TypedAggregation aggregation, String collectionName, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class and are returned as stream. The name of the inputCollection is - * derived from the inputType of the aggregation. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class and are returned as stream. The name + * of the inputCollection is derived from the inputType of the aggregation. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -555,10 +556,10 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN CloseableIterator aggregateStream(TypedAggregation aggregation, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -574,10 +575,10 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN CloseableIterator aggregateStream(Aggregation aggregation, Class inputType, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -1373,10 +1374,9 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * the provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of * domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific - * support. - *
+ * support.
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. 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 88d6202d7c..a795cb5e8e 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 @@ -35,7 +35,6 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -128,11 +127,6 @@ import org.springframework.util.StringUtils; import com.mongodb.ClientSessionOptions; -import com.mongodb.Cursor; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.Mongo; -import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; @@ -174,7 +168,6 @@ * @author Cimon Lucas * @author Michael J. Simons */ -@SuppressWarnings("deprecation") public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider { private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplate.class); @@ -213,18 +206,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, private SessionSynchronization sessionSynchronization = SessionSynchronization.ON_ACTUAL_TRANSACTION; - /** - * Constructor used for a basic template configuration. - * - * @param mongoClient must not be {@literal null}. - * @param databaseName must not be {@literal null} or empty. - * @deprecated since 2.2 in favor of {@link #MongoTemplate(com.mongodb.client.MongoClient, String)}. - */ - @Deprecated - public MongoTemplate(MongoClient mongoClient, String databaseName) { - this(new SimpleMongoDbFactory(mongoClient, databaseName), (MongoConverter) null); - } - /** * Constructor used for a basic template configuration. * @@ -316,8 +297,7 @@ public void setWriteResultChecking(@Nullable WriteResultChecking resultChecking) /** * Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern} - * configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no - * {@link WriteConcern} will be used. + * configured on the {@link MongoDbFactory} will apply. * * @param writeConcern */ @@ -524,8 +504,8 @@ public void executeQuery(Query query, String collectionName, DocumentCallbackHan * specification, must not be {@literal null}. * @param collectionName name of the collection to retrieve the objects from * @param documentCallbackHandler the handler that will extract results, one document at a time - * @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply - * limits, skips and so on). + * @param preparer allows for customization of the {@link FindIterable} used when iterating over the result set, + * (apply limits, skips and so on). */ protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler documentCallbackHandler, @Nullable CursorPreparer preparer) { @@ -2527,8 +2507,8 @@ protected List doFind(String collectionName, Document query, Document fie * @param query the query document that specifies the criteria used to find a record. * @param fields the document that specifies the fields to be returned. * @param entityClass the parameterized type of the returned list. - * @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply - * limits, skips and so on). + * @param preparer allows for customization of the {@link FindIterable} used when iterating over the result set, + * (apply limits, skips and so on). * @return the {@link List} of converted objects. */ protected List doFind(String collectionName, Document query, Document fields, Class entityClass, @@ -2797,16 +2777,16 @@ private T executeFindOneInternal(CollectionCallback collectionCall * Internal method using callback to do queries against the datastore that requires reading a collection of objects. * It will take the following steps *

    - *
  1. Execute the given {@link ConnectionCallback} for a {@link DBCursor}.
  2. - *
  3. Prepare that {@link DBCursor} with the given {@link CursorPreparer} (will be skipped if {@link CursorPreparer} - * is {@literal null}
  4. - *
  5. Iterate over the {@link DBCursor} and applies the given {@link DocumentCallback} to each of the + *
  6. Execute the given {@link ConnectionCallback} for a {@link FindIterable}.
  7. + *
  8. Prepare that {@link FindIterable} with the given {@link CursorPreparer} (will be skipped if + * {@link CursorPreparer} is {@literal null}
  9. + *
  10. Iterate over the {@link FindIterable} and applies the given {@link DocumentCallback} to each of the * {@link Document}s collecting the actual result {@link List}.
  11. *
      * * @param - * @param collectionCallback the callback to retrieve the {@link DBCursor} with - * @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before iterating over it + * @param collectionCallback the callback to retrieve the {@link FindIterable} with + * @param preparer the {@link CursorPreparer} to potentially modify the {@link FindIterable} before iterating over it * @param objectCallback the {@link DocumentCallback} to transform {@link Document}s into the actual domain type * @param collectionName the collection to be queried * @return @@ -2939,7 +2919,7 @@ static RuntimeException potentiallyConvertRuntimeException(RuntimeException ex, /** * Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Oliver Gierke * @author Thomas Risberg @@ -2980,7 +2960,7 @@ public Document doInCollection(MongoCollection collection) throws Mong /** * Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Oliver Gierke * @author Thomas Risberg @@ -3037,7 +3017,7 @@ public Boolean doInCollection(MongoCollection collection) throws Mongo /** * Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Thomas Risberg */ @@ -3304,14 +3284,6 @@ public FindIterable prepare(FindIterable cursor) { cursorToUse = cursorToUse.comment(meta.getComment()); } - if (meta.getSnapshot()) { - cursorToUse = cursorToUse.snapshot(meta.getSnapshot()); - } - - if (meta.getMaxScan() != null) { - cursorToUse = cursorToUse.maxScan(meta.getMaxScan()); - } - if (meta.getMaxTimeMsec() != null) { cursorToUse = cursorToUse.maxTime(meta.getMaxTimeMsec(), TimeUnit.MILLISECONDS); } @@ -3396,7 +3368,7 @@ public GeoResult doWith(@Nullable Document object) { } /** - * A {@link CloseableIterator} that is backed by a MongoDB {@link Cursor}. + * A {@link CloseableIterator} that is backed by a MongoDB {@link MongoCollection}. * * @author Thomas Darimont * @since 1.7 @@ -3409,7 +3381,7 @@ static class CloseableIterableCursorAdapter implements CloseableIterator { private DocumentCallback objectReadCallback; /** - * Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link Cursor}. + * Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link MongoCollection}. * * @param cursor * @param exceptionTranslator diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java index 06ef8307c9..c58292673c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java @@ -22,7 +22,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; -import com.mongodb.async.client.MongoClientSettings; +import com.mongodb.MongoClientSettings; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java index 4809761706..43c3fd7379 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java @@ -15,192 +15,16 @@ */ package org.springframework.data.mongodb.core; -import java.util.ArrayList; -import java.util.List; - -import org.bson.codecs.configuration.CodecRegistry; -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.util.Assert; - -import com.mongodb.MongoCredential; -import com.mongodb.ReadConcern; -import com.mongodb.ReadPreference; -import com.mongodb.WriteConcern; -import com.mongodb.async.client.MongoClientSettings; -import com.mongodb.connection.ClusterSettings; -import com.mongodb.connection.ConnectionPoolSettings; -import com.mongodb.connection.ServerSettings; -import com.mongodb.connection.SocketSettings; -import com.mongodb.connection.SslSettings; -import com.mongodb.connection.StreamFactoryFactory; +import com.mongodb.MongoClientSettings; /** * A factory bean for construction of a {@link MongoClientSettings} instance to be used with the async MongoDB driver. * * @author Mark Paluch * @since 2.0 + * @deprecated since 3.0 - Use {@link MongoClientSettingsFactoryBean} instead. */ -public class ReactiveMongoClientSettingsFactoryBean extends AbstractFactoryBean { - - private static final MongoClientSettings DEFAULT_MONGO_SETTINGS = MongoClientSettings.builder().build(); - - private ReadPreference readPreference = DEFAULT_MONGO_SETTINGS.getReadPreference(); - private WriteConcern writeConcern = DEFAULT_MONGO_SETTINGS.getWriteConcern(); - private ReadConcern readConcern = DEFAULT_MONGO_SETTINGS.getReadConcern(); - private List credentialList = new ArrayList<>(); - private StreamFactoryFactory streamFactoryFactory = DEFAULT_MONGO_SETTINGS.getStreamFactoryFactory(); - private CodecRegistry codecRegistry = DEFAULT_MONGO_SETTINGS.getCodecRegistry(); - private ClusterSettings clusterSettings = DEFAULT_MONGO_SETTINGS.getClusterSettings(); - private SocketSettings socketSettings = DEFAULT_MONGO_SETTINGS.getSocketSettings(); - private SocketSettings heartbeatSocketSettings = DEFAULT_MONGO_SETTINGS.getHeartbeatSocketSettings(); - private ConnectionPoolSettings connectionPoolSettings = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings(); - private ServerSettings serverSettings = DEFAULT_MONGO_SETTINGS.getServerSettings(); - private SslSettings sslSettings = DEFAULT_MONGO_SETTINGS.getSslSettings(); - - /** - * Set the {@link ReadPreference}. - * - * @param readPreference - */ - public void setReadPreference(ReadPreference readPreference) { - this.readPreference = readPreference; - } - - /** - * Set the {@link WriteConcern}. - * - * @param writeConcern - */ - public void setWriteConcern(WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /** - * Set the {@link ReadConcern}. - * - * @param readConcern - */ - public void setReadConcern(ReadConcern readConcern) { - this.readConcern = readConcern; - } - - /** - * Set the List of {@link MongoCredential}s. - * - * @param credentialList must not be {@literal null}. - */ - public void setCredentialList(List credentialList) { - - Assert.notNull(credentialList, "CredendialList must not be null!"); - - this.credentialList.addAll(credentialList); - } - - /** - * Adds the {@link MongoCredential} to the list of credentials. - * - * @param mongoCredential must not be {@literal null}. - */ - public void addMongoCredential(MongoCredential mongoCredential) { - - Assert.notNull(mongoCredential, "MongoCredential must not be null!"); - - this.credentialList.add(mongoCredential); - } - - /** - * Set the {@link StreamFactoryFactory}. - * - * @param streamFactoryFactory - */ - public void setStreamFactoryFactory(StreamFactoryFactory streamFactoryFactory) { - this.streamFactoryFactory = streamFactoryFactory; - } - - /** - * Set the {@link CodecRegistry}. - * - * @param codecRegistry - */ - public void setCodecRegistry(CodecRegistry codecRegistry) { - this.codecRegistry = codecRegistry; - } - - /** - * Set the {@link ClusterSettings}. - * - * @param clusterSettings - */ - public void setClusterSettings(ClusterSettings clusterSettings) { - this.clusterSettings = clusterSettings; - } - - /** - * Set the {@link SocketSettings}. - * - * @param socketSettings - */ - public void setSocketSettings(SocketSettings socketSettings) { - this.socketSettings = socketSettings; - } - - /** - * Set the heartbeat {@link SocketSettings}. - * - * @param heartbeatSocketSettings - */ - public void setHeartbeatSocketSettings(SocketSettings heartbeatSocketSettings) { - this.heartbeatSocketSettings = heartbeatSocketSettings; - } - - /** - * Set the {@link ConnectionPoolSettings}. - * - * @param connectionPoolSettings - */ - public void setConnectionPoolSettings(ConnectionPoolSettings connectionPoolSettings) { - this.connectionPoolSettings = connectionPoolSettings; - } - - /** - * Set the {@link ServerSettings}. - * - * @param serverSettings - */ - public void setServerSettings(ServerSettings serverSettings) { - this.serverSettings = serverSettings; - } - - /** - * Set the {@link SslSettings}. - * - * @param sslSettings - */ - public void setSslSettings(SslSettings sslSettings) { - this.sslSettings = sslSettings; - } - - @Override - public Class getObjectType() { - return MongoClientSettings.class; - } - - @Override - protected MongoClientSettings createInstance() throws Exception { +@Deprecated +public class ReactiveMongoClientSettingsFactoryBean extends MongoClientSettingsFactoryBean { - return MongoClientSettings.builder() // - .readPreference(readPreference) // - .writeConcern(writeConcern) // - .readConcern(readConcern) // - .credentialList(credentialList) // - .streamFactoryFactory(streamFactoryFactory) // - .codecRegistry(codecRegistry) // - .clusterSettings(clusterSettings) // - .socketSettings(socketSettings) // - .heartbeatSocketSettings(heartbeatSocketSettings) // - .connectionPoolSettings(connectionPoolSettings) // - .serverSettings(serverSettings) // - .sslSettings(sslSettings) // - .build(); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index f3c37d1265..203e622e8b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,6 +17,7 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import com.mongodb.client.result.InsertOneResult; import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -123,9 +124,6 @@ import com.mongodb.ClientSessionOptions; import com.mongodb.CursorType; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; @@ -151,7 +149,6 @@ import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.MongoDatabase; -import com.mongodb.reactivestreams.client.Success; /** * Primary implementation of {@link ReactiveMongoOperations}. It simplifies the use of Reactive MongoDB usage and helps @@ -1605,7 +1602,7 @@ protected Mono insertDocument(String collectionName, Document dbDoc, Cla Document document = new Document(dbDoc); - Flux execute = execute(collectionName, collection -> { + Flux execute = execute(collectionName, collection -> { MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName, entityClass, dbDoc, null); @@ -1781,6 +1778,7 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla .ifPresent(updateOptions::collation); if (update.hasArrayFilters()) { + updateOptions.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument) .map(it -> queryMapper.getMappedObject(it, entity)).collect(Collectors.toList())); } @@ -2357,14 +2355,16 @@ protected Flux doFindAndDelete(String collectionName, Query query, Class< protected Mono> doCreateCollection(String collectionName, CreateCollectionOptions collectionOptions) { - return createMono(db -> db.createCollection(collectionName, collectionOptions)).map(success -> { + return createMono(db -> db.createCollection(collectionName, collectionOptions)).doOnSuccess(it -> { - // TODO: Emit a collection created event - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Created collection [{}]", collectionName); - } - return getCollection(collectionName); - }); + + // TODO: Emit a collection created event + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Created collection [{}]", collectionName); + } + + + }).thenReturn(getCollection(collectionName)); } /** @@ -3282,14 +3282,6 @@ public FindPublisher prepare(FindPublisher findPublisher) { findPublisherToUse = findPublisherToUse.comment(meta.getComment()); } - if (meta.getSnapshot()) { - findPublisherToUse = findPublisherToUse.snapshot(meta.getSnapshot()); - } - - if (meta.getMaxScan() != null) { - findPublisherToUse = findPublisherToUse.maxScan(meta.getMaxScan()); - } - if (meta.getMaxTimeMsec() != null) { findPublisherToUse = findPublisherToUse.maxTime(meta.getMaxTimeMsec(), TimeUnit.MILLISECONDS); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java index fd5e0fba85..e076c09bf4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java @@ -21,7 +21,6 @@ import org.springframework.data.mongodb.core.script.NamedMongoScript; import org.springframework.lang.Nullable; -import com.mongodb.DB; /** * Script operations on {@link com.mongodb.DB} level. Allows interaction with server side JavaScript functions. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java index d5d306e877..2743f8abef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java @@ -19,7 +19,6 @@ import com.mongodb.ClientSessionOptions; import com.mongodb.ConnectionString; -import com.mongodb.DB; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; @@ -75,18 +74,6 @@ private SimpleMongoClientDbFactory(MongoClient mongoClient, String databaseName, super(mongoClient, databaseName, mongoInstanceCreated, new MongoExceptionTranslator()); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getLegacyDb() - */ - @Override - public DB getLegacyDb() { - - throw new UnsupportedOperationException(String.format( - "%s does not support legacy DBObject API! Please consider using SimpleMongoDbFactory for that purpose.", - MongoClient.class)); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java deleted file mode 100644 index cdfeaa5091..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2011-2020 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 - * - * https://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 org.springframework.beans.factory.DisposableBean; - -import com.mongodb.ClientSessionOptions; -import com.mongodb.DB; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientURI; -import com.mongodb.client.ClientSession; -import com.mongodb.client.MongoDatabase; - -/** - * Factory to create {@link MongoDatabase} instances from a {@link MongoClient} instance. - * - * @author Mark Pollack - * @author Oliver Gierke - * @author Thomas Darimont - * @author Christoph Strobl - * @author George Moraitis - * @author Mark Paluch - * @deprecated since 2.2 in favor of {@link SimpleMongoClientDbFactory}. - */ -@Deprecated -public class SimpleMongoDbFactory extends MongoDbFactorySupport implements DisposableBean { - - /** - * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClientURI}. - * - * @param uri coordinates for a database connection. Must contain a database name and must not be {@literal null}. - * @since 1.7 - */ - public SimpleMongoDbFactory(MongoClientURI uri) { - this(new MongoClient(uri), uri.getDatabase(), true); - } - - /** - * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClient}. - * - * @param mongoClient must not be {@literal null}. - * @param databaseName must not be {@literal null} or empty. - * @since 1.7 - */ - public SimpleMongoDbFactory(MongoClient mongoClient, String databaseName) { - this(mongoClient, databaseName, false); - } - - /** - * @param mongoClient - * @param databaseName - * @param mongoInstanceCreated - * @since 1.7 - */ - private SimpleMongoDbFactory(MongoClient mongoClient, String databaseName, boolean mongoInstanceCreated) { - super(mongoClient, databaseName, mongoInstanceCreated, new MongoExceptionTranslator()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getLegacyDb() - */ - @Override - public DB getLegacyDb() { - return getMongoClient().getDB(getDefaultDatabaseName()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) - */ - @Override - public ClientSession getSession(ClientSessionOptions options) { - return getMongoClient().startSession(options); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#closeClient() - */ - @Override - protected void closeClient() { - getMongoClient().close(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#doGetMongoDatabase(java.lang.String) - */ - @Override - protected MongoDatabase doGetMongoDatabase(String dbName) { - return getMongoClient().getDatabase(dbName); - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 0a4d99325b..73281a2477 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -116,7 +116,7 @@ public Document fetch(DBRef dbRef) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Fetching DBRef '{}' from {}.{}.", dbRef.getId(), - StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getDb().getName(), + StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getMongoDatabase().getName(), dbRef.getCollectionName()); } @@ -156,7 +156,7 @@ public List bulkFetch(List refs) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Bulk fetching DBRefs {} from {}.{}.", ids, StringUtils.hasText(databaseSource.getDatabaseName()) ? databaseSource.getDatabaseName() - : mongoDbFactory.getDb().getName(), + : mongoDbFactory.getMongoDatabase().getName(), databaseSource.getCollectionName()); } @@ -498,6 +498,6 @@ private synchronized Object resolve() { protected MongoCollection getCollection(DBRef dbref) { return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getDb(dbref.getDatabaseName()) - : mongoDbFactory.getDb()).getCollection(dbref.getCollectionName(), Document.class); + : mongoDbFactory.getMongoDatabase()).getCollection(dbref.getCollectionName(), Document.class); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java index f80f2b858d..446feb8e0e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java @@ -23,8 +23,6 @@ import org.springframework.data.mongodb.core.query.Collation; import org.springframework.lang.Nullable; -import com.mongodb.MapReduceCommand; -import com.mongodb.MapReduceCommand.OutputType; import com.mongodb.client.model.MapReduceAction; /** @@ -38,7 +36,7 @@ public class MapReduceOptions { private @Nullable String outputCollection; private Optional outputDatabase = Optional.empty(); - private MapReduceCommand.OutputType outputType = MapReduceCommand.OutputType.REPLACE; + private @Nullable MapReduceAction mapReduceAction = MapReduceAction.REPLACE; private Map scopeVariables = new HashMap<>(); private Map extraOptions = new HashMap<>(); private @Nullable Boolean jsMode; @@ -103,10 +101,24 @@ public MapReduceOptions outputDatabase(@Nullable String outputDatabase) { * the result set fits within the 16MB limit of a single document. * * @return MapReduceOptions so that methods can be chained in a fluent API style + * @deprecated since 3.0 - Use {@link #actionInline()} instead. */ + @Deprecated public MapReduceOptions outputTypeInline() { + return actionInline(); + } + + /** + * With this option, no collection will be created, and the whole map-reduce operation will happen in RAM. Also, the + * results of the map-reduce will be returned within the result object. Note that this option is possible only when + * the result set fits within the 16MB limit of a single document. + * + * @return this. + * @since 3.0 + */ + public MapReduceOptions actionInline() { - this.outputType = MapReduceCommand.OutputType.INLINE; + this.mapReduceAction = null; return this; } @@ -115,10 +127,23 @@ public MapReduceOptions outputTypeInline() { * result set and the old collection, the new key will overwrite the old one. * * @return MapReduceOptions so that methods can be chained in a fluent API style + * @deprecated since 3.0 - use {@link #actionMerge()} instead. */ + @Deprecated public MapReduceOptions outputTypeMerge() { + return actionMerge(); + } + + /** + * This option will merge new data into the old output collection. In other words, if the same key exists in both the + * result set and the old collection, the new key will overwrite the old one. + * + * @return this. + * @since 3.0 + */ + public MapReduceOptions actionMerge() { - this.outputType = MapReduceCommand.OutputType.MERGE; + this.mapReduceAction = MapReduceAction.MERGE; return this; } @@ -127,22 +152,50 @@ public MapReduceOptions outputTypeMerge() { * specified reduce function) will be performed on the two values and the result will be written to the output * collection. If a finalize function was provided, this will be run after the reduce as well. * - * @return + * @return this. + * @deprecated since 3.0 - use {@link #actionReduce()} instead. */ + @Deprecated public MapReduceOptions outputTypeReduce() { - this.outputType = MapReduceCommand.OutputType.REDUCE; + return actionReduce(); + } + + /** + * If documents exists for a given key in the result set and in the old collection, then a reduce operation (using the + * specified reduce function) will be performed on the two values and the result will be written to the output + * collection. If a finalize function was provided, this will be run after the reduce as well. + * + * @return this. + * @since 3.0 + */ + public MapReduceOptions actionReduce() { + + this.mapReduceAction = MapReduceAction.REDUCE; return this; } /** * The output will be inserted into a collection which will atomically replace any existing collection with the same - * name. Note, the default is MapReduceCommand.OutputType.REPLACE + * name. Note, the default is {@link MapReduceAction#REPLACE}. * * @return MapReduceOptions so that methods can be chained in a fluent API style + * @deprecated since 3.0 - Use {@link #actionReplace()} instead. */ + @Deprecated public MapReduceOptions outputTypeReplace() { + return this.actionReplace(); + } - this.outputType = MapReduceCommand.OutputType.REPLACE; + /** + * The output will be inserted into a collection which will atomically replace any existing collection with the same + * name. Note, the default is {@link MapReduceAction#REPLACE}. + * + * @return MapReduceOptions so that methods can be chained in a fluent API style + * @since 3.0 + */ + public MapReduceOptions actionReplace() { + + this.mapReduceAction = MapReduceAction.REPLACE; return this; } @@ -269,10 +322,6 @@ public Optional getOutputSharded() { return this.outputSharded; } - public MapReduceCommand.OutputType getOutputType() { - return this.outputType; - } - public Map getScopeVariables() { return this.scopeVariables; } @@ -298,34 +347,22 @@ public Optional getCollation() { } /** - * Return the {@link MapReduceAction} derived from {@link com.mongodb.MapReduceCommand.OutputType}. + * Return the {@link MapReduceAction}. * * @return the mapped action or {@literal null} if the action maps to inline output. * @since 2.0.10 */ @Nullable public MapReduceAction getMapReduceAction() { - - switch (outputType) { - case MERGE: - return MapReduceAction.MERGE; - case REDUCE: - return MapReduceAction.REDUCE; - case REPLACE: - return MapReduceAction.REPLACE; - case INLINE: - return null; - default: - throw new IllegalStateException(String.format("Unknown output type %s for map reduce command.", outputType)); - } + return mapReduceAction; } /** - * @return {@literal true} if {@link OutputType#INLINE} is used. + * @return {@literal true} if {@literal inline} output shall is used. * @since 2.0.10 */ public boolean usesInlineOutput() { - return OutputType.INLINE.equals(outputType); + return null == mapReduceAction; } public Document getOptionsObject() { @@ -361,19 +398,20 @@ protected Document createOutObject() { Document out = new Document(); - switch (getOutputType()) { - case INLINE: - out.put("inline", 1); - break; - case REPLACE: - out.put("replace", outputCollection); - break; - case MERGE: - out.put("merge", outputCollection); - break; - case REDUCE: - out.put("reduce", outputCollection); - break; + if (getMapReduceAction() == null) { + out.put("inline", 1); + } else { + switch (getMapReduceAction()) { + case REPLACE: + out.put("replace", outputCollection); + break; + case MERGE: + out.put("merge", outputCollection); + break; + case REDUCE: + out.put("reduce", outputCollection); + break; + } } outputDatabase.ifPresent(val -> out.append("db", val)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java index 918691b3c1..d53c9b2573 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java @@ -22,8 +22,6 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.MapReduceOutput; - /** * Collects the results of performing a MapReduce operations. * @@ -46,9 +44,7 @@ public class MapReduceResults implements Iterable { * * @param mappedResults must not be {@literal null}. * @param rawResults must not be {@literal null}. - * @deprecated since 1.7. Please use {@link #MapReduceResults(List, MapReduceOutput)} */ - @Deprecated public MapReduceResults(List mappedResults, Document rawResults) { Assert.notNull(mappedResults, "List of mapped results must not be null!"); @@ -61,25 +57,6 @@ public MapReduceResults(List mappedResults, Document rawResults) { this.outputCollection = parseOutputCollection(rawResults); } - /** - * Creates a new {@link MapReduceResults} from the given mapped results and the {@link MapReduceOutput}. - * - * @param mappedResults must not be {@literal null}. - * @param mapReduceOutput must not be {@literal null}. - * @since 1.7 - */ - public MapReduceResults(List mappedResults, MapReduceOutput mapReduceOutput) { - - Assert.notNull(mappedResults, "MappedResults must not be null!"); - Assert.notNull(mapReduceOutput, "MapReduceOutput must not be null!"); - - this.mappedResults = mappedResults; - this.rawResults = null; - this.mapReduceTiming = parseTiming(mapReduceOutput); - this.mapReduceCounts = parseCounts(mapReduceOutput); - this.outputCollection = parseOutputCollection(mapReduceOutput); - } - /* * (non-Javadoc) * @see java.lang.Iterable#iterator() @@ -175,17 +152,4 @@ private static String parseOutputCollection(Document rawResults) { return resultField instanceof Document ? ((Document) resultField).get("collection").toString() : resultField.toString(); } - - private static MapReduceCounts parseCounts(final MapReduceOutput mapReduceOutput) { - return new MapReduceCounts(mapReduceOutput.getInputCount(), mapReduceOutput.getEmitCount(), - mapReduceOutput.getOutputCount()); - } - - private static String parseOutputCollection(final MapReduceOutput mapReduceOutput) { - return mapReduceOutput.getCollectionName(); - } - - private static MapReduceTiming parseTiming(MapReduceOutput mapReduceOutput) { - return new MapReduceTiming(-1, -1, mapReduceOutput.getDuration()); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index a9d9bde161..5153493a72 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -57,7 +57,7 @@ interface RequestOptions { * Get the database name of the db. * * @return the name of the database to subscribe to. Can be {@literal null} in which case the default - * {@link MongoDbFactory#getDb() database} is used. + * {@link MongoDbFactory#getMongoDatabase() database} is used. */ @Nullable default String getDatabaseName() { 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 3bff1fb6b3..1addc323e8 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 @@ -108,27 +108,6 @@ public void setMaxTime(Duration timeout) { setValue(MetaKey.MAX_TIME_MS.key, timeout.toMillis()); } - /** - * @return {@literal null} if not set. - * @deprecated since 2.2. {@code $maxScan} has been removed without replacement in MongoDB 4.2. - */ - @Nullable - @Deprecated - public Long getMaxScan() { - return getValue(MetaKey.MAX_SCAN.key); - } - - /** - * Only scan the specified number of documents. - * - * @param maxScan - * @deprecated since 2.1. {@code $maxScan} has been removed without replacement in MongoDB 4.2. - */ - @Deprecated - public void setMaxScan(long maxScan) { - setValue(MetaKey.MAX_SCAN.key, maxScan); - } - /** * Add a comment to the query that is propagated to the profile log. * @@ -146,24 +125,6 @@ public String getComment() { return getValue(MetaKey.COMMENT.key); } - /** - * Using snapshot prevents the cursor from returning a document more than once. - * - * @param useSnapshot - * @deprecated since 2.1 due to deprecation as of MongoDB 3.6 - */ - @Deprecated - public void setSnapshot(boolean useSnapshot) { - setValue(MetaKey.SNAPSHOT.key, useSnapshot); - } - - /** - * @return {@literal null} if not set. - */ - public boolean getSnapshot() { - return getValue(MetaKey.SNAPSHOT.key, false); - } - /** * @return {@literal null} if not set. * @since 2.1 @@ -186,7 +147,7 @@ public void setCursorBatchSize(int cursorBatchSize) { } /** - * Add {@link CursorOption} influencing behavior of the {@link com.mongodb.DBCursor}. + * Add {@link CursorOption} influencing behavior of the {@link com.mongodb.client.FindIterable}. * * @param option must not be {@literal null}. * @return 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 b29763564b..0de6f00760 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 @@ -359,20 +359,6 @@ public Query maxTime(Duration timeout) { return this; } - /** - * @param maxScan - * @return this. - * @see Meta#setMaxScan(long) - * @since 1.6 - * @deprecated since 2.1 due to deprecation in MongoDB 4.0. - */ - @Deprecated - public Query maxScan(long maxScan) { - - meta.setMaxScan(maxScan); - return this; - } - /** * Add a comment to the query that is propagated to the profile log. * @@ -387,19 +373,6 @@ public Query comment(String comment) { return this; } - /** - * @return this. - * @see Meta#setSnapshot(boolean) - * @since 1.6 - * @deprecated since 2.1 due to deprecation as of MongoDB 3.6 - */ - @Deprecated - public Query useSnapshot() { - - meta.setSnapshot(true); - return this; - } - /** * Set the number of documents to return in each response batch.
      * Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java index 19cd8ea18c..62514484f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java @@ -31,11 +31,9 @@ import org.reactivestreams.Publisher; import org.reactivestreams.Subscription; - import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; -import com.mongodb.reactivestreams.client.Success; import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; /** @@ -127,7 +125,7 @@ public Publisher skip(long bytesToSkip) { * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#close() */ @Override - public Publisher close() { + public Publisher close() { return Mono.create(sink -> { @@ -140,7 +138,7 @@ public Publisher close() { } terminatePendingReads(); - sink.success(Success.SUCCESS); + sink.success(); }); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java index 3e303b68c0..359d0fb05c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java @@ -32,7 +32,6 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; -import com.mongodb.reactivestreams.client.Success; import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; /** @@ -131,7 +130,7 @@ public Publisher skip(long bytesToSkip) { * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#close() */ @Override - public Publisher close() { + public Publisher close() { return inputStream.close(); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java index d5db0c1300..2413e76858 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java @@ -23,7 +23,6 @@ import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; -import org.springframework.data.util.Optionals; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -184,7 +183,7 @@ public GridFSFile getGridFSFile() { * * @return never {@literal null}. * @throws com.mongodb.MongoGridFSException in case no content type declared on {@link GridFSFile#getMetadata()} nor - * provided via {@link GridFSFile#getContentType()}. + * provided via {@link GridFSFile}. * @throws IllegalStateException if the file does not {@link #exists()}. */ @SuppressWarnings("deprecation") @@ -192,11 +191,7 @@ public String getContentType() { Assert.state(exists(), () -> String.format("%s does not exist.", getDescription())); - return Optionals - .firstNonEmpty( - () -> Optional.ofNullable(getGridFSFile().getMetadata()) - .map(it -> it.get(CONTENT_TYPE_FIELD, String.class)), - () -> Optional.ofNullable(getGridFSFile().getContentType())) + return Optional.ofNullable(getGridFSFile().getMetadata()).map(it -> it.get(CONTENT_TYPE_FIELD, String.class)) .orElseThrow(() -> new MongoGridFSException("No contentType data for this GridFS file")); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 5cc4524837..3d7b639c2f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -257,7 +257,7 @@ public GridFsResource[] getResources(String locationPattern) { private GridFSBucket getGridFs() { - MongoDatabase db = dbFactory.getDb(); + MongoDatabase db = dbFactory.getMongoDatabase(); return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java index 0366bb761f..94dcac3360 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java @@ -20,8 +20,8 @@ import org.bson.Document; -import com.mongodb.MongoClient; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; import com.mongodb.connection.ServerDescription; @@ -34,22 +34,13 @@ */ public abstract class AbstractMonitor { - private final Object mongoClient; - - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #AbstractMonitor(com.mongodb.client.MongoClient)} - */ - @Deprecated - protected AbstractMonitor(MongoClient mongoClient) { - this.mongoClient = mongoClient; - } + private final MongoClient mongoClient; /** * @param mongoClient * @since 2.2 */ - protected AbstractMonitor(com.mongodb.client.MongoClient mongoClient) { + protected AbstractMonitor(MongoClient mongoClient) { this.mongoClient = mongoClient; } @@ -58,30 +49,16 @@ public Document getServerStatus() { } public MongoDatabase getDb(String databaseName) { - - if (mongoClient instanceof MongoClient) { - return ((MongoClient) mongoClient).getDatabase(databaseName); - } - - return ((com.mongodb.client.MongoClient) mongoClient).getDatabase(databaseName); + return mongoClient.getDatabase(databaseName); } protected MongoClient getMongoClient() { - - if (mongoClient instanceof MongoClient) { - return (MongoClient) mongoClient; - } - - throw new IllegalStateException("A com.mongodb.MongoClient is required but was com.mongodb.client.MongoClient"); + return mongoClient; } protected List hosts() { - if (mongoClient instanceof MongoClient) { - return ((MongoClient) mongoClient).getServerAddressList(); - } - - return ((com.mongodb.client.MongoClient) mongoClient).getClusterDescription().getServerDescriptions().stream() - .map(ServerDescription::getAddress).collect(Collectors.toList()); + return mongoClient.getClusterDescription().getServerDescriptions().stream().map(ServerDescription::getAddress) + .collect(Collectors.toList()); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java index 2819aed42b..7bf4b9b55f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java @@ -15,14 +15,12 @@ */ package org.springframework.data.mongodb.monitor; -import com.mongodb.MongoClient; import org.bson.Document; import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.DBObject; -import com.mongodb.Mongo; +import com.mongodb.client.MongoClient; /** * JMX Metrics for assertions @@ -33,21 +31,10 @@ public class AssertMetrics extends AbstractMonitor { /** - * - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #AssertMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public AssertMetrics(MongoClient mongoClient) { - super(mongoClient); - } - - /** - * * @param mongoClient * @since 2.2 */ - public AssertMetrics(com.mongodb.client.MongoClient mongoClient) { + public AssertMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java index 1cb0a4c995..b56fdf7694 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java @@ -22,7 +22,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Background Flushing @@ -32,20 +32,11 @@ @ManagedResource(description = "Background Flushing Metrics") public class BackgroundFlushingMetrics extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #BackgroundFlushingMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public BackgroundFlushingMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public BackgroundFlushingMetrics(com.mongodb.client.MongoClient mongoClient) { + public BackgroundFlushingMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java index 22e9b985f1..2afec53f22 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for B-tree index counters @@ -30,20 +30,11 @@ @ManagedResource(description = "Btree Metrics") public class BtreeIndexCounters extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #BtreeIndexCounters(com.mongodb.client.MongoClient)} - */ - @Deprecated - public BtreeIndexCounters(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public BtreeIndexCounters(com.mongodb.client.MongoClient mongoClient) { + public BtreeIndexCounters(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java index b56ccdb614..a4b428e017 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Connections @@ -30,21 +30,11 @@ @ManagedResource(description = "Connection metrics") public class ConnectionMetrics extends AbstractMonitor { - /** - * - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #ConnectionMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public ConnectionMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public ConnectionMetrics(com.mongodb.client.MongoClient mongoClient) { + public ConnectionMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java index ea2c783846..23f8813998 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java @@ -21,7 +21,7 @@ import org.springframework.jmx.support.MetricType; import com.mongodb.DBObject; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Global Locks @@ -31,20 +31,11 @@ @ManagedResource(description = "Global Lock Metrics") public class GlobalLockMetrics extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #GlobalLockMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public GlobalLockMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public GlobalLockMetrics(com.mongodb.client.MongoClient mongoClient) { + public GlobalLockMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java index 6ec809f928..7916fbdc27 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Memory @@ -30,20 +30,11 @@ @ManagedResource(description = "Memory Metrics") public class MemoryMetrics extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #MemoryMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public MemoryMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public MemoryMetrics(com.mongodb.client.MongoClient mongoClient) { + public MemoryMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java index b959004af5..4516d5e00e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java @@ -21,7 +21,7 @@ import org.springframework.jmx.support.MetricType; import org.springframework.util.NumberUtils; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Operation counters @@ -31,20 +31,11 @@ @ManagedResource(description = "Operation Counters") public class OperationCounters extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #OperationCounters(com.mongodb.client.MongoClient)} - */ - @Deprecated - public OperationCounters(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public OperationCounters(com.mongodb.client.MongoClient mongoClient) { + public OperationCounters(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java index 0ec3e7ee69..4982e569c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java @@ -21,10 +21,10 @@ import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; - -import com.mongodb.MongoClient; import org.springframework.util.StringUtils; +import com.mongodb.client.MongoClient; + /** * Expose basic server information via JMX * @@ -35,7 +35,11 @@ @ManagedResource(description = "Server Information") public class ServerInfo extends AbstractMonitor { - public ServerInfo(MongoClient mongoClient) { + /** + * @param mongoClient + * @since 2.2 + */ + protected ServerInfo(MongoClient mongoClient) { super(mongoClient); } @@ -52,7 +56,7 @@ public String getHostName() throws UnknownHostException { * UnknownHostException is not necessary anymore, but clients could have * called this method in a try..catch(UnknownHostException) already */ - return StringUtils.collectionToDelimitedString(hosts(), ";"); + return StringUtils.collectionToDelimitedString(hosts(), ","); } @ManagedMetric(displayName = "Uptime Estimate") 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 01977287c6..0d6454b88c 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 @@ -42,15 +42,6 @@ */ long maxExecutionTimeMs() default -1; - /** - * Only scan the specified number of documents. - * - * @return - * @deprecated since 2.2. {@code $maxScan} has been removed without replacement in MongoDB 4.2. - */ - @Deprecated - long maxScanDocuments() default -1; - /** * Sets the number of documents to return per batch.
      * Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single @@ -68,13 +59,6 @@ */ String comment() default ""; - /** - * Using snapshot prevents the cursor from returning a document more than once. - * - * @return - */ - boolean snapshot() default false; - /** * Set {@link org.springframework.data.mongodb.core.query.Meta.CursorOption} to be used when executing query. * 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 466171c2fd..05d864a17d 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 @@ -278,11 +278,6 @@ public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes() metaAttributes.setMaxTimeMsec(meta.maxExecutionTimeMs()); } - if (meta.maxScanDocuments() > 0) { - // TODO: Mongo 4 - removal - metaAttributes.setMaxScan(meta.maxScanDocuments()); - } - if (meta.cursorBatchSize() != 0) { metaAttributes.setCursorBatchSize(meta.cursorBatchSize()); } @@ -291,12 +286,6 @@ public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes() metaAttributes.setComment(meta.comment()); } - if (meta.snapshot()) { - - // TODO: Mongo 4 - removal - metaAttributes.setSnapshot(meta.snapshot()); - } - if (!ObjectUtils.isEmpty(meta.flags())) { for (org.springframework.data.mongodb.core.query.Meta.CursorOption option : meta.flags()) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index f524e14598..1402081516 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -1564,30 +1564,11 @@ private ObjectId readDbPointerIdFromExtendedJson() { return oid; } - @Deprecated - @Override - public void mark() { - if (mark != null) { - throw new BSONException("A mark already exists; it needs to be reset before creating a new one"); - } - mark = new Mark(); - } - @Override public BsonReaderMark getMark() { return new Mark(); } - @Deprecated - @Override - public void reset() { - if (mark == null) { - throw new BSONException("trying to reset a mark before creating it"); - } - mark.reset(); - mark = null; - } - @Override protected Context getContext() { return (Context) super.getContext(); diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd index bc1c52091a..98deb2ac42 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd @@ -29,13 +29,13 @@ schemaLocation="https://www.springframework.org/schema/data/repository/spring-repository.xsd" /> - - + - + @@ -54,10 +54,10 @@ Defines a MongoDbFactory for connecting to a specific database The name of the MongoDbFactory definition (by default "mongoDbFactory").]]> - + @@ -72,7 +72,20 @@ The name of the database to connect to. Default is 'db'. +The MongoClientURI string. +@Deprecated since 3.0 - Use connection-string instead. + ]]> + + + + + + + @@ -325,14 +338,24 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 + + + + + + + + + + - - - - - - + + + + + + @@ -347,6 +370,22 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 + + + + + + + + + + + + + + + + @@ -357,18 +396,18 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 - + - + @@ -380,6 +419,14 @@ The Mongo driver options The name of the MongoClient definition (by default "mongoClient").]]> + + + + + - + - + - + - + + + + - + + + + - + + + + - + + + + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + - + + + + + + diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java index a1dd589558..8e11758747 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java @@ -16,9 +16,10 @@ */ import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; /** * Sample configuration class in default package. @@ -26,11 +27,11 @@ * @author Oliver Gierke */ @Configuration -public class ConfigClassInDefaultPackage extends AbstractMongoConfiguration { +public class ConfigClassInDefaultPackage extends AbstractMongoClientConfiguration { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.config.AbstractMongoConfiguration#getDatabaseName() + * @see org.springframework.data.mongodb.config.AbstractMongoClientConfiguration#getDatabaseName() */ @Override protected String getDatabaseName() { @@ -39,10 +40,10 @@ protected String getDatabaseName() { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.config.AbstractMongoConfiguration#mongo() + * @see org.springframework.data.mongodb.config.AbstractMongoClientConfiguration#mongoClient() */ @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java index 37a7ac3ca0..a9a8ff183c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java @@ -59,7 +59,7 @@ public void setUp() { when(dbFactory.withSession(session)).thenReturn(dbFactory); - when(dbFactory.getDb()).thenReturn(db); + when(dbFactory.getMongoDatabase()).thenReturn(db); when(session.getServerSession()).thenReturn(serverSession); when(session.hasActiveTransaction()).thenReturn(true); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java index 7ceac601e2..fadb174520 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java @@ -60,8 +60,8 @@ public void setUp() { when(dbFactory.withSession(session)).thenReturn(dbFactory); when(dbFactory.withSession(session2)).thenReturn(dbFactory2); - when(dbFactory.getDb()).thenReturn(db); - when(dbFactory2.getDb()).thenReturn(db2); + when(dbFactory.getMongoDatabase()).thenReturn(db); + when(dbFactory2.getMongoDatabase()).thenReturn(db2); when(session.getServerSession()).thenReturn(serverSession); when(session2.getServerSession()).thenReturn(serverSession); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index 862894f734..b4ae2c2b4f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -26,7 +26,6 @@ import java.util.Set; import org.junit.Test; - import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -42,10 +41,11 @@ import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; /** - * Unit tests for {@link AbstractMongoConfiguration}. + * Unit tests for {@link AbstractMongoClientConfiguration}. * * @author Oliver Gierke * @author Thomas Darimont @@ -56,7 +56,7 @@ public class AbstractMongoConfigurationUnitTests { @Test // DATAMONGO-496 public void usesConfigClassPackageAsBaseMappingPackage() throws ClassNotFoundException { - AbstractMongoConfiguration configuration = new SampleMongoConfiguration(); + AbstractMongoClientConfiguration configuration = new SampleMongoConfiguration(); assertThat(configuration.getMappingBasePackage()).isEqualTo(SampleMongoConfiguration.class.getPackage().getName()); assertThat(configuration.getInitialEntitySet()).hasSize(2); assertThat(configuration.getInitialEntitySet()).contains(Entity.class); @@ -134,7 +134,7 @@ public void allowsMultipleEntityBasePackages() throws ClassNotFoundException { private static void assertScanningDisabled(final String value) throws ClassNotFoundException { - AbstractMongoConfiguration configuration = new SampleMongoConfiguration() { + AbstractMongoClientConfiguration configuration = new SampleMongoConfiguration() { @Override protected Collection getMappingBasePackages() { return Collections.singleton(value); @@ -146,7 +146,7 @@ protected Collection getMappingBasePackages() { } @Configuration - static class SampleMongoConfiguration extends AbstractMongoConfiguration { + static class SampleMongoConfiguration extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { @@ -155,7 +155,7 @@ protected String getDatabaseName() { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Bean @@ -174,7 +174,7 @@ public MongoTypeMapper typeMapper() { } } - static class ConfigurationWithMultipleBasePackages extends AbstractMongoConfiguration { + static class ConfigurationWithMultipleBasePackages extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { @@ -183,7 +183,7 @@ protected String getDatabaseName() { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java index 20e37c5c63..49c063ff8c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java @@ -26,7 +26,6 @@ import java.util.Set; import org.junit.Test; - import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -43,9 +42,7 @@ import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.Mongo; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * Unit tests for {@link AbstractReactiveMongoConfiguration}. @@ -81,7 +78,8 @@ public void containsMongoDbFactoryButNoMongoBean() { AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); assertThat(context.getBean(SimpleReactiveMongoDatabaseFactory.class)).isNotNull(); - assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> context.getBean(Mongo.class)); + assertThatExceptionOfType(NoSuchBeanDefinitionException.class) + .isThrownBy(() -> context.getBean(com.mongodb.client.MongoClient.class)); context.close(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java new file mode 100644 index 0000000000..c2d5ce6bbd --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java @@ -0,0 +1,144 @@ +/* + * Copyright 2019 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 + * + * https://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.config; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.test.util.ReflectionTestUtils.*; + +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mongodb.core.MongoClientFactoryBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.connection.ClusterType; + +/** + * Integration tests for the MongoDB namespace. + * + * @author Christoph Strobl + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class MongoClientNamespaceTests { + + @Autowired ApplicationContext ctx; + + @Test // DATAMONGO-2384 + public void clientWithJustHostAndPort() { + + assertThat(ctx.containsBean("client-with-just-host-port")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-just-host-port", + MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isEqualTo("127.0.0.1"); + assertThat(getField(factoryBean, "port")).isEqualTo(27017); + assertThat(getField(factoryBean, "connectionString")).isNull(); + assertThat(getField(factoryBean, "credential")).isNull(); + assertThat(getField(factoryBean, "replicaSet")).isNull(); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithConnectionString() { + + assertThat(ctx.containsBean("client-with-connection-string")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-connection-string", + MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isNull(); + assertThat(getField(factoryBean, "port")).isNull(); + assertThat(getField(factoryBean, "connectionString")) + .isEqualTo(new ConnectionString("mongodb://127.0.0.1:27017/?replicaSet=rs0")); + assertThat(getField(factoryBean, "credential")).isNull(); + assertThat(getField(factoryBean, "replicaSet")).isNull(); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithReplicaSet() { + + assertThat(ctx.containsBean("client-with-replica-set")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-replica-set", + MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isNull(); + assertThat(getField(factoryBean, "port")).isNull(); + assertThat(getField(factoryBean, "connectionString")).isNull(); + assertThat(getField(factoryBean, "credential")).isNull(); + assertThat(getField(factoryBean, "replicaSet")).isEqualTo("rs0"); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithCredential() { + + assertThat(ctx.containsBean("client-with-auth")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-auth", MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isNull(); + assertThat(getField(factoryBean, "port")).isNull(); + assertThat(getField(factoryBean, "connectionString")).isNull(); + assertThat(getField(factoryBean, "credential")).isEqualTo( + Collections.singletonList(MongoCredential.createPlainCredential("jon", "snow", "warg".toCharArray()))); + assertThat(getField(factoryBean, "replicaSet")).isNull(); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithClusterSettings() { + + assertThat(ctx.containsBean("client-with-cluster-settings")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-cluster-settings", + MongoClientFactoryBean.class); + + MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); + + assertThat(settings.getClusterSettings().getRequiredClusterType()).isEqualTo(ClusterType.REPLICA_SET); + assertThat(settings.getClusterSettings().getServerSelectionTimeout(TimeUnit.MILLISECONDS)).isEqualTo(10); + assertThat(settings.getClusterSettings().getLocalThreshold(TimeUnit.MILLISECONDS)).isEqualTo(5); + assertThat(settings.getClusterSettings().getHosts()).contains(new ServerAddress("localhost", 27018), + new ServerAddress("localhost", 27019), new ServerAddress("localhost", 27020)); + } + + @Test // DATAMONGO-2384 + public void clientWithConnectionPoolSettings() { + + assertThat(ctx.containsBean("client-with-connection-pool-settings")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-connection-pool-settings", + MongoClientFactoryBean.class); + + MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); + + assertThat(settings.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS)).isEqualTo(10); + assertThat(settings.getConnectionPoolSettings().getMinSize()).isEqualTo(10); + assertThat(settings.getConnectionPoolSettings().getMaxSize()).isEqualTo(20); + assertThat(settings.getConnectionPoolSettings().getMaintenanceFrequency(TimeUnit.MILLISECONDS)).isEqualTo(10); + assertThat(settings.getConnectionPoolSettings().getMaintenanceInitialDelay(TimeUnit.MILLISECONDS)).isEqualTo(11); + assertThat(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)).isEqualTo(30); + assertThat(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)).isEqualTo(15); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java index f11232506e..62a89ef085 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java @@ -17,6 +17,8 @@ import static org.assertj.core.api.Assertions.*; +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.support.BeanDefinitionReader; @@ -25,11 +27,14 @@ import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; +import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClient; +import com.mongodb.MongoClientSettings; import com.mongodb.MongoCredential; import com.mongodb.ReadPreference; +import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; /** * Integration tests for {@link MongoClientParser}. @@ -62,17 +67,13 @@ public void createsMongoClientWithOptionsCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); - - try { - MongoClient client = context.getBean("mongo-client-with-options-for-write-concern-and-read-preference", - MongoClient.class); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { + context.refresh(); - assertThat(client.getReadPreference()).isEqualTo(ReadPreference.secondary()); - assertThat(client.getWriteConcern()).isEqualTo(WriteConcern.UNACKNOWLEDGED); - } finally { - context.close(); + MongoClientSettings settings = extractClientSettingsFromBean(context, + "mongo-client-with-options-for-write-concern-and-read-preference"); + assertThat(settings.getReadPreference()).isEqualTo(ReadPreference.secondary()); + assertThat(settings.getWriteConcern()).isEqualTo(WriteConcern.UNACKNOWLEDGED); } } @@ -81,16 +82,12 @@ public void createsMongoClientWithDefaultsCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { - try { - MongoClient client = context.getBean("mongoClient", MongoClient.class); + context.refresh(); - assertThat(client.getAddress().getHost()).isEqualTo("127.0.0.1"); - assertThat(client.getAddress().getPort()).isEqualTo(27017); - } finally { - context.close(); + MongoClient client = context.getBean("mongoClient", MongoClient.class); + assertThat(client.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); } } @@ -99,16 +96,14 @@ public void createsMongoClientWithCredentialsCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { + + context.refresh(); - try { - MongoClient client = context.getBean("mongo-client-with-credentials", MongoClient.class); + MongoClientSettings settings = extractClientSettingsFromBean(context, "mongo-client-with-credentials"); - assertThat(client.getCredentialsList()) - .contains(MongoCredential.createPlainCredential("jon", "snow", "warg".toCharArray())); - } finally { - context.close(); + assertThat(settings.getCredential()) + .isEqualTo(MongoCredential.createPlainCredential("jon", "snow", "warg".toCharArray())); } } @@ -117,15 +112,20 @@ public void createsMongoClientWithServerSelectionTimeoutCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { + context.refresh(); - try { - - MongoClient client = context.getBean("mongo-client-with-server-selection-timeout", MongoClient.class); - assertThat(client.getMongoClientOptions().getServerSelectionTimeout()).isEqualTo(100); - } finally { - context.close(); + MongoClientSettings settings = extractClientSettingsFromBean(context, + "mongo-client-with-server-selection-timeout"); + assertThat(settings.getClusterSettings().getServerSelectionTimeout(TimeUnit.MILLISECONDS)).isEqualTo(100); } } + + private MongoClientSettings extractClientSettingsFromBean(AbstractApplicationContext context, String beanName) { + return extractClientSettings(context.getBean(beanName, MongoClient.class)); + } + + private MongoClientSettings extractClientSettings(MongoClient client) { + return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings"); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java index 17e2ebc686..aabb3088d3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java @@ -83,8 +83,6 @@ public class MongoCredentialPropertyEditorUnitTests { static final MongoCredential USER_2_CREDENTIALS = MongoCredential.createCredential(USER_2_NAME, USER_2_DB, USER_2_PWD.toCharArray()); - static final MongoCredential USER_2_CREDENTIALS_CR_AUTH = MongoCredential.createMongoCRCredential(USER_2_NAME, - USER_2_DB, USER_2_PWD.toCharArray()); static final MongoCredential USER_3_CREDENTIALS_X509_AUTH = MongoCredential.createMongoX509Credential(USER_3_NAME); @@ -176,16 +174,6 @@ public void shouldReturnCredentialsValueCorrectlyWhenGivenMultipleUserNamePasswo assertThat(getValue()).contains(USER_1_CREDENTIALS, USER_2_CREDENTIALS); } - @Test // DATAMONGO-1158 - @SuppressWarnings("unchecked") - public void shouldReturnCredentialsValueCorrectlyWhenGivenMultipleUserNamePasswordStringWithDatabaseAndAuthOptions() { - - editor.setAsText(StringUtils.collectionToCommaDelimitedString(Arrays - .asList(USER_1_AUTH_STRING_WITH_PLAIN_AUTH_MECHANISM, USER_2_AUTH_STRING_WITH_MONGODB_CR_AUTH_MECHANISM))); - - assertThat(getValue()).contains(USER_1_CREDENTIALS_PLAIN_AUTH, USER_2_CREDENTIALS_CR_AUTH); - } - @Test // DATAMONGO-1158 @SuppressWarnings("unchecked") public void shouldReturnCredentialsValueCorrectlyWhenGivenMultipleUserNamePasswordStringWithDatabaseAndMixedOptions() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 1195e78962..9736077eae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -30,12 +30,10 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClientURI; -import com.mongodb.MongoURI; +import com.mongodb.ConnectionString; import com.mongodb.WriteConcern; import com.mongodb.client.MongoDatabase; @@ -62,7 +60,7 @@ public void testWriteConcern() throws Exception { SimpleMongoClientDbFactory dbFactory = new SimpleMongoClientDbFactory(MongoTestUtils.client(), "database"); dbFactory.setWriteConcern(WriteConcern.ACKNOWLEDGED); - dbFactory.getDb(); + dbFactory.getMongoDatabase(); assertThat(ReflectionTestUtils.getField(dbFactory, "writeConcern")).isEqualTo(WriteConcern.ACKNOWLEDGED); } @@ -88,7 +86,7 @@ public void readsReplicasWriteConcernCorrectly() { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext( "namespace/db-factory-bean-custom-write-concern.xml"); MongoDbFactory factory = ctx.getBean("second", MongoDbFactory.class); - MongoDatabase db = factory.getDb(); + MongoDatabase db = factory.getMongoDatabase(); assertThat(db.getWriteConcern()).isEqualTo(WriteConcern.W2); ctx.close(); @@ -119,11 +117,11 @@ public void setsUpMongoDbFactoryUsingAMongoUriWithoutCredentials() { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); MongoDbFactory dbFactory = factory.getBean("mongoDbFactory", MongoDbFactory.class); - MongoDatabase db = dbFactory.getDb(); + MongoDatabase db = dbFactory.getMongoDatabase(); assertThat(db.getName()).isEqualTo("database"); } @@ -135,7 +133,7 @@ public void setsUpMongoDbFactoryUsingAMongoClientUri() { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); } @@ -147,7 +145,7 @@ public void setsUpClientUriWithId() { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); } @@ -159,24 +157,42 @@ public void setsUpUriWithId() { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); } + @Test // DATAMONGO-2384 + public void usesConnectionStringToCreateClientClient() { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml"); + + MongoDbFactory dbFactory = ctx.getBean("with-connection-string", MongoDbFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + assertThat(ReflectionTestUtils.getField(dbFactory, "mongoClient")) + .isInstanceOf(com.mongodb.client.MongoClient.class); + } + + @Test // DATAMONGO-2384 + public void usesMongoClientClientRef() { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml"); + + MongoDbFactory dbFactory = ctx.getBean("with-mongo-client-client-ref", MongoDbFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + assertThat(ReflectionTestUtils.getField(dbFactory, "mongoClient")) + .isInstanceOf(com.mongodb.client.MongoClient.class); + } + private static void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) { - SimpleMongoDbFactory dbFactory = ctx.getBean("first", SimpleMongoDbFactory.class); - MongoDatabase db = dbFactory.getDb(); + SimpleMongoClientDbFactory dbFactory = ctx.getBean("first", SimpleMongoClientDbFactory.class); + MongoDatabase db = dbFactory.getMongoDatabase(); assertThat(db.getName()).isEqualTo("db"); WriteConcern configuredConcern = (WriteConcern) ReflectionTestUtils.getField(dbFactory, "writeConcern"); - MyWriteConcern myDbFactoryWriteConcern = new MyWriteConcern(configuredConcern); - MyWriteConcern myDbWriteConcern = new MyWriteConcern(db.getWriteConcern()); - MyWriteConcern myExpectedWriteConcern = new MyWriteConcern(expectedWriteConcern); - - assertThat(myDbFactoryWriteConcern).isEqualTo(myExpectedWriteConcern); - assertThat(myDbWriteConcern).isEqualTo(myExpectedWriteConcern); - assertThat(myDbWriteConcern).isEqualTo(myDbFactoryWriteConcern); + assertThat(configuredConcern).isEqualTo(expectedWriteConcern); + assertThat(db.getWriteConcern()).isEqualTo(expectedWriteConcern); + assertThat(db.getWriteConcern()).isEqualTo(expectedWriteConcern); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java index a3f1c89847..f04cf44f11 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java @@ -22,11 +22,11 @@ import java.util.ArrayList; import java.util.List; +import com.mongodb.MongoClientSettings; import org.bson.Document; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.core.MongoClientFactoryBean; @@ -35,11 +35,10 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClient; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; /** - * * @author Mark Pollack * @author Oliver Gierke * @author Thomas Darimont @@ -58,7 +57,8 @@ public void testParsingMongoWithReplicaSets() throws Exception { assertThat(ctx.containsBean("replicaSetMongo")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&replicaSetMongo"); - List replicaSetSeeds = (List) ReflectionTestUtils.getField(mfb, "replicaSetSeeds"); + MongoClientSettings settings = (MongoClientSettings) ReflectionTestUtils.getField(mfb, "mongoClientSettings"); + List replicaSetSeeds = settings.getClusterSettings().getHosts(); assertThat(replicaSetSeeds).isNotNull(); assertThat(replicaSetSeeds).contains(new ServerAddress(InetAddress.getByName("127.0.0.1"), 10001), @@ -72,7 +72,8 @@ public void testParsingWithPropertyPlaceHolder() throws Exception { assertThat(ctx.containsBean("manyReplicaSetMongo")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&manyReplicaSetMongo"); - List replicaSetSeeds = (List) ReflectionTestUtils.getField(mfb, "replicaSetSeeds"); + MongoClientSettings settings = (MongoClientSettings) ReflectionTestUtils.getField(mfb, "mongoClientSettings"); + List replicaSetSeeds = settings.getClusterSettings().getHosts(); assertThat(replicaSetSeeds).isNotNull(); assertThat(replicaSetSeeds).hasSize(3); @@ -90,8 +91,8 @@ public void testParsingWithPropertyPlaceHolder() throws Exception { public void testMongoWithReplicaSets() { MongoClient mongo = ctx.getBean(MongoClient.class); - assertThat(mongo.getAllAddress().size()).isEqualTo(2); - List servers = mongo.getAllAddress(); + assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).isEqualTo(2); + List servers = mongo.getClusterDescription().getClusterSettings().getHosts(); assertThat(servers.get(0).getHost()).isEqualTo("127.0.0.1"); assertThat(servers.get(1).getHost()).isEqualTo("localhost"); assertThat(servers.get(0).getPort()).isEqualTo(10001); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index f37fba8631..e6139a6781 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -22,7 +22,6 @@ import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.MongoDbFactory; @@ -33,9 +32,10 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import com.mongodb.MongoClientSettings; +import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; /** * Integration tests for the MongoDB namespace. @@ -74,9 +74,8 @@ public void testMongoSingletonWithAttributes() throws Exception { assertThat(host).isEqualTo("localhost"); assertThat(port).isEqualTo(new Integer(27017)); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory) - .as("By default socketFactory should not be a SSLSocketFactory").isFalse(); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); + assertThat(options).isNull(); } @Test // DATAMONGO-764 @@ -85,9 +84,9 @@ public void testMongoSingletonWithSslEnabled() throws Exception { assertThat(ctx.containsBean("mongoSsl")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoSsl"); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory).as("socketFactory should be a SSLSocketFactory") - .isTrue(); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); + assertThat(options.getSslSettings().getContext().getSocketFactory() instanceof SSLSocketFactory) + .as("socketFactory should be a SSLSocketFactory").isTrue(); } @Test // DATAMONGO-1490 @@ -96,9 +95,9 @@ public void testMongoClientSingletonWithSslEnabled() { assertThat(ctx.containsBean("mongoClientSsl")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoClientSsl"); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory).as("socketFactory should be a SSLSocketFactory") - .isTrue(); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); + assertThat(options.getSslSettings().getContext().getSocketFactory() instanceof SSLSocketFactory) + .as("socketFactory should be a SSLSocketFactory").isTrue(); } @Test // DATAMONGO-764 @@ -107,12 +106,11 @@ public void testMongoSingletonWithSslEnabledAndCustomSslSocketFactory() throws E assertThat(ctx.containsBean("mongoSslWithCustomSslFactory")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoSslWithCustomSslFactory"); - SSLSocketFactory customSslSocketFactory = ctx.getBean("customSslSocketFactory", SSLSocketFactory.class); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory).as("socketFactory should be a SSLSocketFactory") - .isTrue(); - assertThat(options.getSocketFactory()).isSameAs(customSslSocketFactory); + assertThat(options.getSslSettings().getContext().getSocketFactory() instanceof SSLSocketFactory) + .as("socketFactory should be a SSLSocketFactory").isTrue(); + assertThat(options.getSslSettings().getContext().getProvider().getName()).isEqualTo("SunJSSE"); } @Test @@ -122,8 +120,7 @@ public void testSecondMongoDbFactory() { MongoDbFactory dbf = (MongoDbFactory) ctx.getBean("secondMongoDbFactory"); MongoClient mongo = (MongoClient) getField(dbf, "mongoClient"); - assertThat(mongo.getAddress().getHost()).isEqualTo("127.0.0.1"); - assertThat(mongo.getAddress().getPort()).isEqualTo(27017); + assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); } @@ -135,8 +132,7 @@ public void testThirdMongoDbFactory() { MongoDbFactory dbf = (MongoDbFactory) ctx.getBean("thirdMongoDbFactory"); MongoClient mongo = (MongoClient) getField(dbf, "mongoClient"); - assertThat(mongo.getAddress().getHost()).isEqualTo("127.0.0.1"); - assertThat(mongo.getAddress().getPort()).isEqualTo(27017); + assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); } @@ -163,7 +159,7 @@ public void testSecondMongoTemplateFactory() { assertThat(getField(dbf, "databaseName")).isEqualTo("database"); WriteConcern writeConcern = (WriteConcern) getField(operations, "writeConcern"); - assertThat(writeConcern).isEqualTo(WriteConcern.SAFE); + assertThat(writeConcern).isEqualTo(WriteConcern.ACKNOWLEDGED); } @Test // DATAMONGO-628 @@ -220,15 +216,15 @@ public void testMongoSingletonWithPropertyPlaceHolders() throws Exception { assertThat(host).isEqualTo("127.0.0.1"); assertThat(port).isEqualTo(new Integer(27017)); - MongoClient mongo = mfb.getObject(); - MongoClientOptions mongoOpts = mongo.getMongoClientOptions(); - - assertThat(mongoOpts.getConnectionsPerHost()).isEqualTo(8); - assertThat(mongoOpts.getConnectTimeout()).isEqualTo(1000); - assertThat(mongoOpts.getMaxWaitTime()).isEqualTo(1500); - - assertThat(mongoOpts.getSocketTimeout()).isEqualTo(1500); - assertThat(mongoOpts.getThreadsAllowedToBlockForConnectionMultiplier()).isEqualTo(4); + // MongoClient mongo = mfb.getObject(); + // MongoClientSettings mongoOpts = mongo.getClusterDescription()..getMongoClientSettings(); + // + // assertThat(mongoOpts.getConnectionsPerHost()).isEqualTo(8); + // assertThat(mongoOpts.getConnectTimeout()).isEqualTo(1000); + // assertThat(mongoOpts.getMaxWaitTime()).isEqualTo(1500); + // + // assertThat(mongoOpts.getSocketTimeout()).isEqualTo(1500); + // assertThat(mongoOpts.getThreadsAllowedToBlockForConnectionMultiplier()).isEqualTo(4); // TODO: check the damned defaults // assertEquals("w", mongoOpts.getWriteConcern().getW()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java index 13afa1ec98..0547a97a76 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java @@ -19,7 +19,9 @@ import java.util.List; +import com.mongodb.client.MongoClient; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.PropertyValue; @@ -31,10 +33,9 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; -import com.mongodb.Mongo; /** - * Integration tests for {@link MongoParser}. + * Integration tests for {@link MongoClientParser}. * * @author Oliver Gierke */ @@ -51,6 +52,7 @@ public void setUp() { } @Test + @Ignore public void readsMongoAttributesCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-bean.xml")); @@ -58,6 +60,7 @@ public void readsMongoAttributesCorrectly() { List values = definition.getPropertyValues().getPropertyValueList(); + values.forEach(System.out::println); assertThat(values.get(2).getValue()).isInstanceOf(BeanDefinition.class); BeanDefinition x = (BeanDefinition) values.get(2).getValue(); @@ -74,7 +77,7 @@ public void readsServerAddressesCorrectly() { AbstractApplicationContext context = new GenericApplicationContext(factory); context.refresh(); - assertThat(context.getBean("mongo2", Mongo.class)).isNotNull(); + assertThat(context.getBean("mongo2", MongoClient.class)).isNotNull(); context.close(); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java deleted file mode 100644 index 725a9cd26b..0000000000 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.springframework.data.mongodb.config; - -import com.mongodb.WriteConcern; - -public class MyWriteConcern { - - public MyWriteConcern(WriteConcern wc) { - this._w = wc.getWObject(); - this._fsync = wc.getFsync(); - this._j = wc.getJ(); - this._wtimeout = wc.getWtimeout(); - } - - Object _w = 0; - int _wtimeout = 0; - boolean _fsync = false; - boolean _j = false; - boolean _continueOnErrorForInsert = false; - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (_continueOnErrorForInsert ? 1231-2018 : 1237); - result = prime * result + (_fsync ? 1231-2018 : 1237); - result = prime * result + (_j ? 1231-2018 : 1237); - result = prime * result + ((_w == null) ? 0 : _w.hashCode()); - result = prime * result + _wtimeout; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MyWriteConcern other = (MyWriteConcern) obj; - if (_continueOnErrorForInsert != other._continueOnErrorForInsert) - return false; - if (_fsync != other._fsync) - return false; - if (_j != other._j) - return false; - if (_w == null) { - if (other._w != null) - return false; - } else if (!_w.equals(other._w)) - return false; - if (_wtimeout != other._wtimeout) - return false; - return true; - } - -} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 4c99339957..d35056d096 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -100,7 +100,7 @@ public class DefaultBulkOperationsUnitTests { @Before public void setUp() { - when(factory.getDb()).thenReturn(database); + when(factory.getMongoDatabase()).thenReturn(database); when(factory.getExceptionTranslator()).thenReturn(new NullExceptionTranslator()); when(database.getCollection(anyString(), eq(Document.class))).thenReturn(collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java index 8f215f66a0..1a7b11ef28 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java @@ -62,7 +62,7 @@ public class DefaultIndexOperationsUnitTests { @Before public void setUp() { - when(factory.getDb()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(), any(Class.class))).thenReturn(collection); when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn("OK"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index dedf2aafc5..816c5d03ba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -89,7 +89,7 @@ public void setUp() { this.indexOps = new DefaultReactiveIndexOperations(template, collectionName, new QueryMapper(template.getConverter())); - StepVerifier.create(this.collection.dropIndexes()).expectNextCount(1).verifyComplete(); + StepVerifier.create(this.collection.dropIndexes()).verifyComplete(); } private void queryMongoVersionIfNecessary() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java index d4b376767a..83ee459b94 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java @@ -24,8 +24,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.DB; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * This test class assumes that you are already running the MongoDB server. @@ -38,8 +37,6 @@ public class MongoAdminIntegrationTests { private static final Log logger = LogFactory.getLog(MongoAdminIntegrationTests.class); - @SuppressWarnings("unused") private DB testAdminDb; - @Autowired MongoClient mongoClient; MongoAdmin mongoAdmin; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java new file mode 100644 index 0000000000..fc9e3320fa --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019. 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. + */ + +/* + * Copyright 2019 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 + * + * https://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.*; + +import java.util.concurrent.TimeUnit; + +import com.mongodb.ServerAddress; +import org.junit.jupiter.api.Test; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; + +/** + * @author Christoph Strobl + */ +class MongoClientFactoryBeanUnitTests { + + static final String CONNECTION_STRING_STRING = "mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000"; + static final ConnectionString CONNECTION_STRING = new ConnectionString(CONNECTION_STRING_STRING); + + @Test // DATAMONGO-2427 + void connectionStringParametersNotOverriddenByDefaults() { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setConnectionString(CONNECTION_STRING); + factoryBean.setMongoClientSettings(MongoClientSettings.builder().build()); + + MongoClientSettings settings = factoryBean.computeClientSetting(); + + assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("test"); + assertThat(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300000); + assertThat(settings.getClusterSettings().getHosts()).hasSize(2); + } + + @Test // DATAMONGO-2427 + void hostPortParametersNotOverriddenByDefaults() { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setPort(2500); + factoryBean.setHost("db2.example.net"); + factoryBean.setReplicaSet("rs0"); + factoryBean.setMongoClientSettings(MongoClientSettings.builder().build()); + + MongoClientSettings settings = factoryBean.computeClientSetting(); + + assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("rs0"); + assertThat(settings.getClusterSettings().getHosts()).containsExactly(new ServerAddress("db2.example.net", 2500)); + } + + @Test // DATAMONGO-2427 + void explicitSettingsOverrideConnectionStringOnes() { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setConnectionString(CONNECTION_STRING); + factoryBean.setMongoClientSettings( + MongoClientSettings.builder().applyToClusterSettings(it -> it.requiredReplicaSetName("rs0")) + .applyToSocketSettings(it -> it.connectTimeout(100, TimeUnit.MILLISECONDS)).build()); + + MongoClientSettings settings = factoryBean.computeClientSetting(); + + assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("rs0"); + assertThat(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(100); + assertThat(settings.getClusterSettings().getHosts()).hasSize(2); + } + + @Test // DATAMONGO-2427 + void hostAndPortPlusConnectionStringError() throws Exception { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setConnectionString(CONNECTION_STRING); + factoryBean.setHost("localhost"); + factoryBean.setPort(27017); + assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> factoryBean.createInstance()); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java similarity index 86% rename from spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java index 4e141f171a..9d884a38f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java @@ -27,16 +27,16 @@ import com.mongodb.ReadPreference; /** - * Integration tests for {@link MongoClientOptionsFactoryBean}. + * Integration tests for {@link MongoClientSettingsFactoryBean}. * * @author Christoph Strobl */ -public class MongoClientOptionsFactoryBeanIntegrationTests { +public class MongoClientSettingsFactoryBeanIntegrationTests { @Test // DATAMONGO-1158 public void convertsReadPreferenceConcernCorrectly() { - RootBeanDefinition definition = new RootBeanDefinition(MongoClientOptionsFactoryBean.class); + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); definition.getPropertyValues().addPropertyValue("readPreference", "NEAREST"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); @@ -44,7 +44,7 @@ public void convertsReadPreferenceConcernCorrectly() { factory.registerBeanDefinition("factory", definition); - MongoClientOptionsFactoryBean bean = factory.getBean("&factory", MongoClientOptionsFactoryBean.class); + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); assertThat(ReflectionTestUtils.getField(bean, "readPreference")).isEqualTo((Object) ReadPreference.nearest()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java new file mode 100644 index 0000000000..4b5cf6ddb0 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java @@ -0,0 +1,66 @@ +/* + * Copyright 2019 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 + * + * https://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.*; + +import org.junit.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.data.mongodb.config.ReadConcernPropertyEditor; +import org.springframework.data.mongodb.config.ReadPreferencePropertyEditor; +import org.springframework.test.util.ReflectionTestUtils; + +import com.mongodb.ReadConcern; +import com.mongodb.ReadPreference; + +/** + * Integration tests for {@link MongoClientSettingsFactoryBean}. + * + * @author Christoph Strobl + */ +public class MongoClientSettingsFactoryBeanUnitTests { + + @Test // DATAMONGO-2384 + public void convertsReadPreferenceConcernCorrectly() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); + definition.getPropertyValues().addPropertyValue("readPreference", "NEAREST"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerCustomEditor(ReadPreference.class, ReadPreferencePropertyEditor.class); + + factory.registerBeanDefinition("factory", definition); + + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "readPreference")).isEqualTo(ReadPreference.nearest()); + } + + @Test // DATAMONGO-2384 + public void convertsReadConcernConcernCorrectly() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); + definition.getPropertyValues().addPropertyValue("readConcern", "MAJORITY"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerCustomEditor(ReadPreference.class, ReadConcernPropertyEditor.class); + + factory.registerBeanDefinition("factory", definition); + + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "readConcern")).isEqualTo(ReadConcern.MAJORITY); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 7dca9fd5cd..44dee0ad71 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -100,12 +100,12 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBRef; -import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; import com.mongodb.client.FindIterable; import com.mongodb.client.ListIndexesIterable; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.model.Filters; @@ -410,7 +410,7 @@ public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() throws Exc assertThat(template.indexOps(Person.class).getIndexInfo().isEmpty()).isTrue(); - factory.getDb().getCollection(template.getCollectionName(Person.class)) + factory.getMongoDatabase().getCollection(template.getCollectionName(Person.class)) .createIndex(new org.bson.Document("age", -1), new IndexOptions().name("age_-1").unique(true).sparse(true)); ListIndexesIterable indexInfo = template.getCollection(template.getCollectionName(Person.class)) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 0a93c42c21..7b6d1dfc95 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -96,7 +96,6 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; -import com.mongodb.DB; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.ReadPreference; @@ -157,7 +156,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { public void beforeEach() { when(findIterable.iterator()).thenReturn(cursor); - when(factory.getDb()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(String.class), eq(Document.class))).thenReturn(collection); when(db.runCommand(any(), any(Class.class))).thenReturn(commandResultDocument); 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 index 166463272d..68dacbcc69 100644 --- 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 @@ -33,7 +33,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.core.CollectionOptions.ValidationOptions; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; 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 8867c51fc1..59ddf9f26b 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 @@ -31,7 +31,6 @@ import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; -import org.springframework.data.mongodb.core.query.Meta; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.FindIterable; @@ -57,9 +56,7 @@ public void setUp() { when(cursor.batchSize(anyInt())).thenReturn(cursor); when(cursor.comment(anyString())).thenReturn(cursor); when(cursor.maxTime(anyLong(), any())).thenReturn(cursor); - when(cursor.maxScan(anyLong())).thenReturn(cursor); when(cursor.hint(any())).thenReturn(cursor); - when(cursor.snapshot(anyBoolean())).thenReturn(cursor); when(cursor.noCursorTimeout(anyBoolean())).thenReturn(cursor); when(cursor.collation(any())).thenReturn(cursor); } @@ -82,25 +79,25 @@ public void appliesDocumentHintsCorrectly() { verify(cursor).hint(new Document("age", 1)); } - @Test // DATAMONGO-957 - public void doesNotApplyMetaWhenEmpty() { - - Query query = query(where("foo").is("bar")); - query.setMeta(new Meta()); - - prepare(query); - - verify(cursor, never()).modifiers(any(Document.class)); - } - - @Test // DATAMONGO-957 - public void appliesMaxScanCorrectly() { - - Query query = query(where("foo").is("bar")).maxScan(100); - prepare(query); - - verify(cursor).maxScan(100); - } +// @Test // DATAMONGO-957 +// public void doesNotApplyMetaWhenEmpty() { +// +// Query query = query(where("foo").is("bar")); +// query.setMeta(new Meta()); +// +// prepare(query); +// +// verify(cursor, never()).modifiers(any(Document.class)); +// } + + // @Test // DATAMONGO-957 + // public void appliesMaxScanCorrectly() { + // + // Query query = query(where("foo").is("bar")).maxScan(100); + // prepare(query); + // + // verify(cursor).maxScan(100); + // } @Test // DATAMONGO-957 public void appliesMaxTimeCorrectly() { @@ -120,14 +117,14 @@ public void appliesCommentCorrectly() { verify(cursor).comment("spring data"); } - @Test // DATAMONGO-957 - public void appliesSnapshotCorrectly() { - - Query query = query(where("foo").is("bar")).useSnapshot(); - prepare(query); - - verify(cursor).snapshot(true); - } +// @Test // DATAMONGO-957 +// public void appliesSnapshotCorrectly() { +// +// Query query = query(where("foo").is("bar")).useSnapshot(); +// prepare(query); +// +// verify(cursor).snapshot(true); +// } @Test // DATAMONGO-1480 public void appliesNoCursorTimeoutCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java index d0a2369b76..012edc39ca 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java @@ -39,7 +39,6 @@ import com.mongodb.ClientSessionOptions; import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.Success; /** * @author Christoph Strobl @@ -66,7 +65,6 @@ public void setUp() { MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, COLLECTION_NAME, client) // .as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); template.insert(new Document("_id", "id-1").append("value", "spring"), COLLECTION_NAME) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java index 234fa90e1f..6fdf4d8701 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java @@ -41,7 +41,6 @@ import com.mongodb.ClientSessionOptions; import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.Success; /** * Integration tests for Mongo Transactions using {@link ReactiveMongoTemplate}. @@ -76,15 +75,12 @@ public void setUp() { template = new ReactiveMongoTemplate(client, DATABASE_NAME); MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, COLLECTION_NAME, client).as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); - MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, "person", client).as(StepVerifier::create) - .expectNext(Success.SUCCESS) // - .verifyComplete(); + MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, "person", client).as(StepVerifier::create).verifyComplete(); MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, "personWithVersionPropertyOfTypeInteger", client) - .as(StepVerifier::create).expectNext(Success.SUCCESS) // + .as(StepVerifier::create) // .verifyComplete(); template.insert(DOCUMENT, COLLECTION_NAME).as(StepVerifier::create).expectNextCount(1).verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 0bd0d49909..6bd65c2f16 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -93,7 +93,6 @@ import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.MongoDatabase; -import com.mongodb.reactivestreams.client.Success; /** * Unit tests for {@link ReactiveMongoTemplate}. @@ -116,7 +115,7 @@ public class ReactiveMongoTemplateUnitTests { @Mock Publisher runCommandPublisher; @Mock Publisher updateResultPublisher; @Mock Publisher findAndUpdatePublisher; - @Mock Publisher successPublisher; + @Mock Publisher successPublisher; @Mock DistinctPublisher distinctPublisher; @Mock Publisher deletePublisher; @Mock MapReducePublisher mapReducePublisher; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java index 519b3c748c..bb63134515 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java @@ -127,7 +127,6 @@ public void setUp() { when(findPublisher.collation(any())).thenReturn(findPublisher); when(findPublisher.first()).thenReturn(resultPublisher); when(aggregatePublisher.allowDiskUse(anyBoolean())).thenReturn(aggregatePublisher); - when(aggregatePublisher.useCursor(anyBoolean())).thenReturn(aggregatePublisher); factory = new SimpleReactiveMongoDatabaseFactory(client, "foo"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java index 33410cee61..1c721753a2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java @@ -20,7 +20,6 @@ import static org.springframework.data.mongodb.core.query.Query.*; import lombok.Data; -import org.springframework.data.mongodb.test.util.MongoTestUtils; import reactor.test.StepVerifier; import org.bson.BsonString; @@ -30,9 +29,7 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; - -import com.mongodb.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; +import org.springframework.data.mongodb.test.util.MongoTestUtils; /** * Integration tests for {@link ReactiveUpdateOperationSupport}. @@ -51,7 +48,8 @@ public class ReactiveUpdateOperationSupportTests { @Before public void setUp() { - blocking = new MongoTemplate(new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); + blocking = new MongoTemplate( + new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); blocking.dropCollection(STAR_WARS); han = new Person(); @@ -116,8 +114,7 @@ public void updateAll() { public void updateAllMatching() { template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han")).all() - .as(StepVerifier::create) - .consumeNextWith(actual -> { + .as(StepVerifier::create).consumeNextWith(actual -> { assertThat(actual.getModifiedCount()).isEqualTo(1L); assertThat(actual.getUpsertedId()).isNull(); @@ -128,8 +125,7 @@ public void updateAllMatching() { public void updateWithDifferentDomainClassAndCollection() { template.update(Jedi.class).inCollection(STAR_WARS).matching(query(where("_id").is(han.getId()))) - .apply(new Update().set("name", "Han")).all().as(StepVerifier::create) - .consumeNextWith(actual -> { + .apply(new Update().set("name", "Han")).all().as(StepVerifier::create).consumeNextWith(actual -> { assertThat(actual.getModifiedCount()).isEqualTo(1L); assertThat(actual.getUpsertedId()).isNull(); @@ -143,8 +139,7 @@ public void updateWithDifferentDomainClassAndCollection() { public void findAndModify() { template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han")).findAndModify() - .as(StepVerifier::create) - .expectNext(han).verifyComplete(); + .as(StepVerifier::create).expectNext(han).verifyComplete(); assertThat(blocking.findOne(queryHan(), Person.class)).isNotEqualTo(han).hasFieldOrPropertyWithValue("firstname", "Han"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java index b49ff97944..22acab58ae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java @@ -100,9 +100,9 @@ public void setUp() { MongoDbFactory factory = new SimpleMongoClientDbFactory(client, "session-bound-mongo-template-tests") { @Override - public MongoDatabase getDb() throws DataAccessException { + public MongoDatabase getMongoDatabase() throws DataAccessException { - MongoDatabase spiedDatabse = Mockito.spy(super.getDb()); + MongoDatabase spiedDatabse = Mockito.spy(super.getMongoDatabase()); spiedDatabases.add(spiedDatabse); return spiedDatabse; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java index 41b62aa2b6..eee395f824 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java @@ -112,7 +112,6 @@ public void setUp() { when(aggregateIterable.allowDiskUse(anyBoolean())).thenReturn(aggregateIterable); when(aggregateIterable.batchSize(anyInt())).thenReturn(aggregateIterable); when(aggregateIterable.map(any())).thenReturn(aggregateIterable); - when(aggregateIterable.useCursor(anyBoolean())).thenReturn(aggregateIterable); when(aggregateIterable.into(any())).thenReturn(Collections.emptyList()); when(mongoIterable.iterator()).thenReturn(cursor); when(distinctIterable.map(any())).thenReturn(distinctIterable); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java similarity index 84% rename from spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java index 8a2961e620..7369c82727 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java @@ -30,20 +30,20 @@ import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClientURI; +import com.mongodb.ConnectionString; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; /** - * Unit tests for {@link SimpleMongoDbFactory}. + * Unit tests for {@link SimpleMongoClientDbFactory}. * * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) -public class SimpleMongoDbFactoryUnitTests { +public class SimpleMongoClientDbFactoryUnitTests { @Mock MongoClient mongo; @Mock ClientSession clientSession; @@ -72,8 +72,9 @@ public void allowsDatabaseNames() { @SuppressWarnings("deprecation") public void mongoUriConstructor() { - MongoClientURI mongoURI = new MongoClientURI("mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); - MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoURI); + ConnectionString mongoURI = new ConnectionString( + "mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); + MongoDbFactory mongoDbFactory = new SimpleMongoClientDbFactory(mongoURI); assertThat(getField(mongoDbFactory, "databaseName").toString()).isEqualTo("myDatabase"); } @@ -81,8 +82,9 @@ public void mongoUriConstructor() { @Test // DATAMONGO-1158 public void constructsMongoClientAccordingToMongoUri() { - MongoClientURI uri = new MongoClientURI("mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); - SimpleMongoDbFactory factory = new SimpleMongoDbFactory(uri); + ConnectionString uri = new ConnectionString( + "mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); + SimpleMongoClientDbFactory factory = new SimpleMongoClientDbFactory(uri); assertThat(getField(factory, "databaseName").toString()).isEqualTo("myDataBase"); } @@ -95,7 +97,7 @@ public void cascadedWithSessionUsesRootFactory() { MongoDbFactory factory = new SimpleMongoClientDbFactory(mongo, "foo"); MongoDbFactory wrapped = factory.withSession(clientSession).withSession(clientSession); - InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getDb()); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase()); Object singletonTarget = AopProxyUtils .getSingletonTarget(ReflectionTestUtils.getField(invocationHandler, "advised")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index d0a7f44cf5..b4f97ce988 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -173,13 +173,14 @@ public void shouldRenderNestedParameterExpressionResults() { @Test // DATAMONGO-774 public void shouldRenderNestedParameterExpressionResultsInNestedExpressions() { + Document target = ((Document) transform( + "((1 + [0].primitiveLongValue) + [0].primitiveDoubleValue) * [0].doubleValue.longValue()", data)); + assertThat( ((Document) transform("((1 + [0].primitiveLongValue) + [0].primitiveDoubleValue) * [0].doubleValue.longValue()", - data)).toJson()) + data))) .isEqualTo(new Document("$multiply", - Arrays. asList( - new Document("$add", Arrays. asList(1, new Document("$numberLong", "42"), 1.2345D)), - new Document("$numberLong", "23"))).toJson()); + Arrays. asList(new Document("$add", Arrays. asList(1, 42L, 1.2345D)), 23L))); } @Test // DATAMONGO-840 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index e98a4136b9..a4a321ea4a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -29,7 +29,6 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.Version; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.config.EnableMongoAuditing; import org.springframework.data.mongodb.core.KAuditableVersionedEntity; import org.springframework.data.mongodb.core.MongoTemplate; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index 88eca20b34..4bb8d0a30f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -111,7 +111,7 @@ public void convertDocumentWithMapDBRef() { MongoDatabase dbMock = mock(MongoDatabase.class); MongoCollection collectionMock = mock(MongoCollection.class); - when(dbFactory.getDb()).thenReturn(dbMock); + when(dbFactory.getMongoDatabase()).thenReturn(dbMock); when(dbMock.getCollection(anyString(), eq(Document.class))).thenReturn(collectionMock); FindIterable fi = mock(FindIterable.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index 0fab4c3976..9033f5c5c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -59,7 +59,7 @@ public class DefaultDbRefResolverUnitTests { @Before public void setUp() { - when(factoryMock.getDb()).thenReturn(dbMock); + when(factoryMock.getMongoDatabase()).thenReturn(dbMock); when(dbMock.getCollection(anyString(), any(Class.class))).thenReturn(collectionMock); when(collectionMock.find(any(Document.class))).thenReturn(cursorMock); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 9d116974e0..daf6bd064c 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -28,6 +28,9 @@ import java.util.Map; import java.util.Optional; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.model.Filters; +import org.bson.conversions.Bson; import org.bson.types.Code; import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; @@ -58,7 +61,6 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -import com.mongodb.QueryBuilder; /** * Unit tests for {@link QueryMapper}. @@ -179,8 +181,8 @@ void handlesEnumsInNotEqualCorrectly() { @Test // DATAMONGO-373 void handlesNativelyBuiltQueryCorrectly() { - DBObject query = new QueryBuilder().or(new BasicDBObject("foo", "bar")).get(); - mapper.getMappedObject(new org.bson.Document(query.toMap()), Optional.empty()); + Bson query = new BasicDBObject(Filters.or(new BasicDBObject("foo", "bar")).toBsonDocument(org.bson.Document.class, MongoClientSettings.getDefaultCodecRegistry())); + mapper.getMappedObject(query, Optional.empty()); } @Test // DATAMONGO-369 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 5e585ac2ed..7f40c174a4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -31,7 +31,6 @@ import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -39,7 +38,6 @@ import org.springframework.data.mongodb.MongoCollectionUtils; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index eddf555efc..def6e4ee1d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -74,7 +74,7 @@ public void setUp() { optionsCaptor = ArgumentCaptor.forClass(IndexOptions.class); collectionCaptor = ArgumentCaptor.forClass(String.class); - when(factory.getDb()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); when(db.getCollection(collectionCaptor.capture(), eq(org.bson.Document.class))) .thenReturn((MongoCollection) collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java index faef0f359e..2b58196b41 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java @@ -18,10 +18,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.test.util.MongoTestUtils; import com.mongodb.client.MongoClient; -import org.springframework.data.mongodb.test.util.MongoTestUtils; @Configuration public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java index cebdf0a04c..8f02df5d0b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java @@ -40,7 +40,6 @@ import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoCollection; -import com.mongodb.reactivestreams.client.Success; /** * @author Christoph Strobl @@ -125,8 +124,7 @@ public void mapReduceWithOutputCollection() { template .mapReduce(new Query(), ValueObject.class, "jmr1", ValueObject.class, mapFunction, reduceFunction, MapReduceOptions.options().outputCollection("jmr1_out")) - .as(StepVerifier::create) - .expectNextCount(4).verifyComplete(); + .as(StepVerifier::create).expectNextCount(4).verifyComplete(); template.find(new Query(), ValueObject.class, "jmr1_out").buffer(4).as(StepVerifier::create) // .consumeNextWith(result -> { @@ -144,8 +142,7 @@ public void mapReduceWithOutputDatabase() { template .mapReduce(new Query(), ValueObject.class, "jmr1", ValueObject.class, mapFunction, reduceFunction, MapReduceOptions.options().outputDatabase("reactive-jrm1-out-db").outputCollection("jmr1_out")) - .as(StepVerifier::create) - .expectNextCount(4).verifyComplete(); + .as(StepVerifier::create).expectNextCount(4).verifyComplete(); Flux.from(factory.getMongoDatabase("reactive-jrm1-out-db").listCollectionNames()).buffer(10) .map(list -> list.contains("jmr1_out")).as(StepVerifier::create).expectNext(true).verifyComplete(); @@ -186,8 +183,8 @@ public void mapReduceWithInlineFilterQueryAndExtractedCollection() { @Test // DATAMONGO-1890 public void throwsExceptionWhenTryingToLoadFunctionsFromDisk() { - assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> template.mapReduce(new Query(), Person.class, - "foo", ValueObject.class, "classpath:map.js", "classpath:reduce.js", MapReduceOptions.options())) + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> template.mapReduce(new Query(), + Person.class, "foo", ValueObject.class, "classpath:map.js", "classpath:reduce.js", MapReduceOptions.options())) .withMessageContaining("classpath:map.js"); } @@ -198,7 +195,8 @@ private void createMapReduceData() { StepVerifier .create(collection.insertMany(Arrays.asList(new Document("x", Arrays.asList("a", "b")), new Document("x", Arrays.asList("b", "c")), new Document("x", Arrays.asList("c", "d"))))) - .expectNext(Success.SUCCESS).verifyComplete(); + .expectNextCount(1) // + .verifyComplete(); } @org.springframework.data.mongodb.core.mapping.Document("jmr1") diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index a41b3e25fe..770055049b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -213,7 +213,7 @@ public void shouldStartReceivingMessagesWhenContainerStarts() throws Interrupted @Test // DATAMONGO-1803 public void tailableCursor() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -235,7 +235,7 @@ public void tailableCursor() throws InterruptedException { @Test // DATAMONGO-1803 public void tailableCursorOnEmptyCollection() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); MessageListenerContainer container = new DefaultMessageListenerContainer(template); @@ -256,7 +256,7 @@ public void tailableCursorOnEmptyCollection() throws InterruptedException { @Test // DATAMONGO-1803 public void abortsSubscriptionOnError() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); MessageListenerContainer container = new DefaultMessageListenerContainer(template); @@ -284,7 +284,7 @@ public void abortsSubscriptionOnError() throws InterruptedException { @Test // DATAMONGO-1803 public void callsDefaultErrorHandlerOnError() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -316,7 +316,7 @@ public void callsDefaultErrorHandlerOnError() throws InterruptedException { @EnableIfReplicaSetAvailable public void runsMoreThanOneTaskAtOnce() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); MessageListenerContainer container = new DefaultMessageListenerContainer(template); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java index 2ea0e52862..a62ad17522 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java @@ -38,8 +38,6 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.messaging.Message.MessageProperties; import org.springframework.data.mongodb.core.messaging.TailableCursorRequest.TailableCursorRequestOptions; - -import com.mongodb.MongoClient; import org.springframework.data.mongodb.test.util.MongoTestUtils; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java index 2495eb1f79..af3d35348a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java @@ -39,7 +39,7 @@ public class GridFsResourceUnitTests { public void shouldReadContentTypeCorrectly() { Document metadata = new Document(GridFsResource.CONTENT_TYPE_FIELD, "text/plain"); - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", metadata); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), metadata); GridFsResource resource = new GridFsResource(file); assertThat(resource.getContentType()).isEqualTo("text/plain"); @@ -48,7 +48,7 @@ public void shouldReadContentTypeCorrectly() { @Test // DATAMONGO-2240 public void shouldReturnGridFSFile() { - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", new Document()); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), new Document()); GridFsResource resource = new GridFsResource(file); assertThat(resource.getGridFSFile()).isSameAs(file); @@ -57,7 +57,7 @@ public void shouldReturnGridFSFile() { @Test // DATAMONGO-1850 public void shouldThrowExceptionOnEmptyContentType() { - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", null); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), null); GridFsResource resource = new GridFsResource(file); assertThatThrownBy(resource::getContentType).isInstanceOf(MongoGridFSException.class); @@ -66,7 +66,7 @@ public void shouldThrowExceptionOnEmptyContentType() { @Test // DATAMONGO-1850 public void shouldThrowExceptionOnEmptyContentTypeInMetadata() { - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", new Document()); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), new Document()); GridFsResource resource = new GridFsResource(file); assertThatThrownBy(resource::getContentType).isInstanceOf(MongoGridFSException.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 12e323bfb5..2944aff945 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.UUID; import java.util.stream.Stream; import org.bson.BsonObjectId; @@ -36,14 +35,13 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -52,8 +50,6 @@ import com.mongodb.MongoGridFSException; import com.mongodb.client.gridfs.GridFSFindIterable; import com.mongodb.client.gridfs.model.GridFSFile; -import com.mongodb.gridfs.GridFS; -import com.mongodb.gridfs.GridFSInputFile; /** * Integration tests for {@link GridFsTemplate}. @@ -73,7 +69,7 @@ public class GridFsTemplateIntegrationTests { Resource resource = new ClassPathResource("gridfs/gridfs.xml"); @Autowired GridFsOperations operations; - @Autowired SimpleMongoDbFactory mongoClient; + @Autowired SimpleMongoClientDbFactory mongoClient; @Before public void setUp() { @@ -92,23 +88,23 @@ public void storesAndFindsSimpleDocument() throws IOException { assertThat(((BsonObjectId) files.get(0).getId()).getValue()).isEqualTo(reference); } - @Test // DATAMONGO-2392 - public void storesAndFindsByUUID() throws IOException { - - UUID uuid = UUID.randomUUID(); - - GridFS fs = new GridFS(mongoClient.getLegacyDb()); - GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); - - in.put("_id", uuid); - in.put("contentType", "application/octet-stream"); - in.save(); - - GridFSFile file = operations.findOne(query(where("_id").is(uuid))); - GridFsResource resource = operations.getResource(file); - - assertThat(resource.exists()).isTrue(); - } + // @Test // DATAMONGO-2392 + // public void storesAndFindsByUUID() throws IOException { + // + // UUID uuid = UUID.randomUUID(); + // + // GridFSFile fs = new GridFSFile(new BsonObjectId(new ObjectId(uuid.to)) + // GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); + // + // in.put("_id", uuid); + // in.put("contentType", "application/octet-stream"); + // in.save(); + // + // GridFSFile file = operations.findOne(query(where("_id").is(uuid))); + // GridFsResource resource = operations.getResource(file); + // + // assertThat(resource.exists()).isTrue(); + // } @Test // DATAMONGO-6 public void writesMetadataCorrectly() throws IOException { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 0b18d36620..6656a6cada 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -26,7 +26,6 @@ import java.io.IOException; import java.nio.ByteBuffer; -import java.util.UUID; import org.bson.BsonObjectId; import org.bson.Document; @@ -46,7 +45,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; @@ -54,8 +53,6 @@ import org.springframework.util.StreamUtils; import com.mongodb.client.gridfs.model.GridFSFile; -import com.mongodb.gridfs.GridFS; -import com.mongodb.gridfs.GridFSInputFile; import com.mongodb.internal.HexUtils; import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; import com.mongodb.reactivestreams.client.gridfs.helpers.AsyncStreamHelper; @@ -75,7 +72,7 @@ public class ReactiveGridFsTemplateTests { Resource resource = new ClassPathResource("gridfs/gridfs.xml"); @Autowired ReactiveGridFsOperations operations; - @Autowired SimpleMongoDbFactory mongoClient; + @Autowired SimpleMongoClientDbFactory mongoClient; @Autowired ReactiveMongoDatabaseFactory dbFactory; @Autowired MongoConverter mongoConverter; @@ -143,24 +140,24 @@ public void storesAndLoadsLargeFileCorrectly() { }).verifyComplete(); } - @Test // DATAMONGO-2392 - public void storesAndFindsByUUID() throws IOException { - - UUID uuid = UUID.randomUUID(); - - GridFS fs = new GridFS(mongoClient.getLegacyDb()); - GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); - - in.put("_id", uuid); - in.put("contentType", "application/octet-stream"); - in.save(); - - operations.findOne(query(where("_id").is(uuid))).flatMap(operations::getResource) - .flatMapMany(ReactiveGridFsResource::getDownloadStream) // - .transform(DataBufferUtils::join) // - .doOnNext(DataBufferUtils::release).as(StepVerifier::create) // - .expectNextCount(1).verifyComplete(); - } + // @Test // DATAMONGO-2392 + // public void storesAndFindsByUUID() throws IOException { + // + // UUID uuid = UUID.randomUUID(); + // + // GridFS fs = new GridFS(mongoClient.getLegacyDb()); + // GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); + // + // in.put("_id", uuid); + // in.put("contentType", "application/octet-stream"); + // in.save(); + // + // operations.findOne(query(where("_id").is(uuid))).flatMap(operations::getResource) + // .flatMapMany(ReactiveGridFsResource::getDownloadStream) // + // .transform(DataBufferUtils::join) // + // .doOnNext(DataBufferUtils::release).as(StepVerifier::create) // + // .expectNextCount(1).verifyComplete(); + // } @Test // DATAMONGO-1855 public void writesMetadataCorrectly() throws IOException { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java index ae4f74e0a8..fcb1cd91dc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java @@ -26,7 +26,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * This test class assumes that you are already running the MongoDB server. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java index 723b0acb9f..94542b541c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java @@ -60,7 +60,7 @@ public interface UserWithComplexIdRepository extends CrudRepository { @Meta(maxExecutionTimeMs = 100) List metaWithSpellFixedMaxExecutionTime(); - @Meta(maxScanDocuments = 10) - List metaWithMaxScan(); - @Meta(comment = "foo bar") List metaWithComment(); - @Meta(snapshot = true) - List metaWithSnapshotUsage(); - @Meta(flags = { org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT }) List metaWithNoCursorTimeout(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 7a3a7fb459..4261c56a1f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -28,15 +28,15 @@ import java.util.Map; import java.util.UUID; -import org.bson.BSON; +import org.bson.BsonBinarySubType; import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; - import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.MongoOperations; @@ -319,7 +319,7 @@ public void shouldSupportNonQuotedBinaryDataReplacement() { org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { '$binary' : '" - + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BSON.B_GENERAL + "'}}"); + + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BsonBinarySubType.BINARY.getValue() + "'}}"); assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); } @@ -334,7 +334,7 @@ public void shouldSupportNonQuotedBinaryCollectionDataReplacement() { org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { $in: [{'$binary' : '" - + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BSON.B_GENERAL + "'}] }}"); + + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BsonBinarySubType.BINARY.getValue() + "'}] }}"); assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java index cabd2022fa..2b3bec6470 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java @@ -32,10 +32,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import com.mongodb.DB; -import com.mongodb.DBCollection; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 258f0625f1..3924b50abd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -30,7 +30,6 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.reactivestreams.client.MongoClients; -import com.mongodb.reactivestreams.client.Success; /** * Utility to create (and reuse) imperative and reactive {@code MongoClient} instances. @@ -109,7 +108,7 @@ public static MongoCollection createOrReplaceCollection(String dbName, * @param collectionName must not be {@literal null}. * @param client must not be {@literal null}. */ - public static Mono createOrReplaceCollection(String dbName, String collectionName, + public static Mono createOrReplaceCollection(String dbName, String collectionName, com.mongodb.reactivestreams.client.MongoClient client) { com.mongodb.reactivestreams.client.MongoDatabase database = client.getDatabase(dbName) @@ -134,7 +133,6 @@ public static void createOrReplaceCollectionNow(String dbName, String collection createOrReplaceCollection(dbName, collectionName, client) // .as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); } @@ -155,7 +153,6 @@ public static void dropCollectionNow(String dbName, String collectionName, Mono.from(database.getCollection(collectionName).drop()) // .retryBackoff(3, Duration.ofMillis(250)) // .as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); } @@ -180,9 +177,9 @@ public static void flushCollection(String dbName, String collectionName, } /** - * Create a new {@link com.mongodb.MongoClient} with defaults suitable for replica set usage. + * Create a new {@link com.mongodb.client.MongoClient} with defaults suitable for replica set usage. * - * @return new instance of {@link com.mongodb.MongoClient}. + * @return new instance of {@link com.mongodb.client.MongoClient}. */ public static com.mongodb.client.MongoClient replSetClient() { return com.mongodb.client.MongoClients.create(CONNECTION_STRING); diff --git a/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml b/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml index 91e90f010c..d6aeec9d55 100644 --- a/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml +++ b/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml @@ -32,7 +32,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/infrastructure.xml b/spring-data-mongodb/src/test/resources/infrastructure.xml index 9a8d1fc9ea..5a80d0aca7 100644 --- a/spring-data-mongodb/src/test/resources/infrastructure.xml +++ b/spring-data-mongodb/src/test/resources/infrastructure.xml @@ -8,7 +8,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml index 3f75c8b79d..66dba8540a 100644 --- a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml +++ b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml @@ -5,10 +5,10 @@ xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + diff --git a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml index ae9f93a645..6f8c1ae0cf 100644 --- a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml +++ b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml @@ -5,10 +5,18 @@ xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + + + + + + + + + diff --git a/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml b/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml index be74ee6124..478f95daf0 100644 --- a/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml +++ b/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml @@ -6,9 +6,11 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + + + diff --git a/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml b/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml index 20ade07f36..0659bfb973 100644 --- a/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml +++ b/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml @@ -8,16 +8,16 @@ - + - - + + - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml new file mode 100644 index 0000000000..912d318ba1 --- /dev/null +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml index 5602dcf347..dc86edce2f 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml @@ -8,11 +8,11 @@ http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml index 247f153bd5..5575248498 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml @@ -10,9 +10,13 @@ - + + + - + + + - + - - @@ -61,7 +55,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties index 4ac86e45af..ac0a3e9045 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties @@ -11,4 +11,6 @@ mongo.fsync=true mongo.slaveOk=true mongoSsl.ssl=true +replicaSetName=rs0 +credential=jon:warg@snow?uri.authMechanism=PLAIN diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml index 7d1ccaee17..05eba28ac5 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -12,7 +12,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml index b5cd79f2b4..839d6b2f44 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml @@ -14,7 +14,7 @@ - + diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 66dfee37cf..11533441ba 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -14,6 +14,7 @@ toc::[] include::preface.adoc[] include::new-features.adoc[leveloffset=+1] +include::upgrading.adoc[leveloffset=+1] include::{spring-data-commons-docs}/dependencies.adoc[leveloffset=+1] include::{spring-data-commons-docs}/repositories.adoc[leveloffset=+1] diff --git a/src/main/asciidoc/reference/client-session-transactions.adoc b/src/main/asciidoc/reference/client-session-transactions.adoc index 7e345c4969..6343ae54e5 100644 --- a/src/main/asciidoc/reference/client-session-transactions.adoc +++ b/src/main/asciidoc/reference/client-session-transactions.adoc @@ -302,7 +302,7 @@ The following example shows how to create and use transactions with a `ReactiveM [source,java] ---- @Configuration -static class Config extends AbstractMongoConfiguration { +static class Config extends AbstractMongoClientConfiguration { @Bean ReactiveMongoTransactionManager transactionManager(ReactiveDatabaseFactory factory) { <1> diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index da2b7a58c5..8aed432387 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -252,18 +252,18 @@ calling `get()` before the actual conversion Unless explicitly configured, an instance of `MappingMongoConverter` is created by default when you create a `MongoTemplate`. You can create your own instance of the `MappingMongoConverter`. Doing so lets you dictate where in the classpath your domain classes can be found, so that Spring Data MongoDB can extract metadata and construct indexes. Also, by creating your own instance, you can register Spring converters to map specific classes to and from the database. -You can configure the `MappingMongoConverter` as well as `com.mongodb.MongoClient` and MongoTemplate by using either Java-based or XML-based metadata. The following example uses Spring's Java-based configuration: +You can configure the `MappingMongoConverter` as well as `com.mongodb.client.MongoClient` and MongoTemplate by using either Java-based or XML-based metadata. The following example uses Spring's Java-based configuration: .@Configuration class to configure MongoDB mapping support ==== [source,java] ---- @Configuration -public class GeoSpatialAppConfig extends AbstractMongoConfiguration { +public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { @Bean public MongoClient mongoClient() { - return new MongoClient("localhost"); + return MongoClients.create("monogodb://localhost:27017"); } @Override @@ -296,11 +296,11 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration { ---- ==== -`AbstractMongoConfiguration` requires you to implement methods that define a `com.mongodb.MongoClient` as well as provide a database name. `AbstractMongoConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. +`AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. You can add additional converters to the converter by overriding the `customConversions` method. Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure. -NOTE: `AbstractMongoConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`. +NOTE: `AbstractMongoClientConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`. Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows: diff --git a/src/main/asciidoc/reference/migrating.adoc b/src/main/asciidoc/reference/migrating.adoc new file mode 100644 index 0000000000..81cfb0780c --- /dev/null +++ b/src/main/asciidoc/reference/migrating.adoc @@ -0,0 +1,61 @@ +[[migrating]] += Migrating + +This chapter coverts major changes and outlines migration steps. + +[[migrating-2.x-to-3.0]] +== 2.x to 3.0 + +=== Dependency Changes + +* `org.mongodb:mongo-java-driver` (uber jar) got replaced with: +** bson-jar +** core-jar +** sync-jar + + +This allows to include eg. just the reactive bits without having to pull in all the sync stuff. +NOTE: The new sync driver does no longer support `com.mongodb.DBObject`. Please use `org.bson.Document` instead. + +=== Signature Changes + +* `MongoTemplate` no longer supports `com.mongodb.MongoClient` and `com.mongodb.MongoClientOptions`. +Please use `com.mongodb.client.MongoClient` and `com.mongodb.MongoClientSettings` instead. + +In case you're using `AbstractMongoConfiguration` please switch to `AbstractMongoClientInformation`. + +=== Namespace Changes + +The switch to `com.mongodb.client.MongoClient` requires an update of your configuration XML if you have one. +The best way to provide required connection information is by using a connection string. +Please see the https://docs.mongodb.com/manual/reference/connection-string/[MongoDB Documentation] for details. + +[source,xml] +==== +---- + +---- + +---- + + + + + +---- + +---- + + + +---- +==== + + + diff --git a/src/main/asciidoc/reference/mongo-auditing.adoc b/src/main/asciidoc/reference/mongo-auditing.adoc index 90a8e5ce7f..eabc532c0c 100644 --- a/src/main/asciidoc/reference/mongo-auditing.adoc +++ b/src/main/asciidoc/reference/mongo-auditing.adoc @@ -1,16 +1,6 @@ [[mongo.auditing]] == General Auditing Configuration for MongoDB -To activate auditing functionality, add the Spring Data Mongo `auditing` namespace element to your configuration, as the following example shows: - -.Activating auditing by using XML configuration -==== -[source,xml] ----- - ----- -==== - Since Spring Data MongoDB 1.4, auditing can be enabled by annotating a configuration class with the `@EnableMongoAuditing` annotation, as the followign example shows: .Activating auditing using JavaConfig @@ -28,5 +18,15 @@ class Config { } ---- ==== - If you expose a bean of type `AuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableMongoAuditing`. + +To activate auditing functionality via XML, add the Spring Data Mongo `auditing` namespace element to your configuration, as the following example shows: + +.Activating auditing by using XML configuration +==== +[source,xml] +---- + +---- +==== + diff --git a/src/main/asciidoc/reference/mongo-custom-conversions.adoc b/src/main/asciidoc/reference/mongo-custom-conversions.adoc index c823e6a817..c4707f389c 100644 --- a/src/main/asciidoc/reference/mongo-custom-conversions.adoc +++ b/src/main/asciidoc/reference/mongo-custom-conversions.adoc @@ -85,6 +85,32 @@ public class PersonReadConverter implements Converter { [[mongo.custom-converters.xml]] === Registering Spring Converters with the `MongoConverter` +[source,java] +---- +class MyMongoConfiguration extends AbstractMongoClientConfiguration { + + @Override + public String getDatabaseName() { + return "database"; + } + + @Override + @Bean + public MongoClient mongoClient() { + return MongoClients.create(); + } + + @Override + public CustomConversions customConversions() { + + List> converters = new ArrayList<>(2); + converters.add(new com.example.PersonReadConverter()); + converters.add(new com.example.PersonWriteConverter()); + return new MongoCustomConversions(converters); + } +} +---- + The Mongo Spring namespace provides a convenient way to register Spring `Converter` instances with the `MappingMongoConverter`. The following configuration snippet shows how to manually register converter beans as well as configure the wrapping `MappingMongoConverter` into a `MongoTemplate`: [source,xml] @@ -95,12 +121,12 @@ The Mongo Spring namespace provides a convenient way to register Spring `Convert - + - + diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index c6c2341fbb..a97ccf93be 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -41,9 +41,42 @@ public interface PersonRepository extends PagingAndSortingRepository>, by using the standard `com.mongodb.MongoClient` object and the name of the database to use. +* You can instantiate the central helper class of Spring Mongo, <>, by using the standard `com.mongodb.client.MongoClient` object and the name of the database to use. * The mapper works against standard POJO objects without the need for any additional metadata (though you can optionally provide that information. See <>.). * Conventions are used for handling the `id` field, converting it to be an `ObjectId` when stored in the database. * Mapping conventions can use field access. Notice that the `Person` class has only getters. @@ -165,16 +165,16 @@ There is a https://github.com/spring-projects/spring-data-examples[GitHub reposi [[mongodb-connectors]] == Connecting to MongoDB with Spring -One of the first tasks when using MongoDB and Spring is to create a `com.mongodb.MongoClient` or `com.mongodb.client.MongoClient` object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections. +One of the first tasks when using MongoDB and Spring is to create a `com.mongodb.client.MongoClient` or `com.mongodb.client.MongoClient` object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections. NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.0.html#new-java-configuration[here] as well as the detailed documentation https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#beans-java-instantiating-container[here]. [[mongo.mongo-java-config]] === Registering a Mongo Instance by using Java-based Metadata -The following example shows an example of using Java-based bean metadata to register an instance of a `com.mongodb.MongoClient`: +The following example shows an example of using Java-based bean metadata to register an instance of a `com.mongodb.client.MongoClient`: -.Registering a `com.mongodb.MongoClient` object using Java-based bean metadata +.Registering a `com.mongodb.client.MongoClient` object using Java-based bean metadata ==== [source,java] ---- @@ -182,20 +182,20 @@ The following example shows an example of using Java-based bean metadata to regi public class AppConfig { /* - * Use the standard Mongo driver API to create a com.mongodb.MongoClient instance. + * Use the standard Mongo driver API to create a com.mongodb.client.MongoClient instance. */ public @Bean MongoClient mongoClient() { - return new MongoClient("localhost"); + return MongoClients.create("mongodb://localhost:27017"); } } ---- ==== -This approach lets you use the standard `com.mongodb.MongoClient` instance, with the container using Spring's `MongoClientFactoryBean`. As compared to instantiating a `com.mongodb.MongoClient` instance directly, the `FactoryBean` has the added advantage of also providing the container with an `ExceptionTranslator` implementation that translates MongoDB exceptions to exceptions in Spring's portable `DataAccessException` hierarchy for data access classes annotated with the `@Repository` annotation. This hierarchy and the use of `@Repository` is described in https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html[Spring's DAO support features]. +This approach lets you use the standard `com.mongodb.client.MongoClient` instance, with the container using Spring's `MongoClientFactoryBean`. As compared to instantiating a `com.mongodb.client.MongoClient` instance directly, the `FactoryBean` has the added advantage of also providing the container with an `ExceptionTranslator` implementation that translates MongoDB exceptions to exceptions in Spring's portable `DataAccessException` hierarchy for data access classes annotated with the `@Repository` annotation. This hierarchy and the use of `@Repository` is described in https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html[Spring's DAO support features]. The following example shows an example of a Java-based bean metadata that supports exception translation on `@Repository` annotated classes: -.Registering a `com.mongodb.MongoClient` object by using Spring's MongoClientFactoryBean and enabling Spring's exception translation support +.Registering a `com.mongodb.client.MongoClient` object by using Spring's `MongoClientFactoryBean` and enabling Spring's exception translation support ==== [source,java] ---- @@ -203,7 +203,7 @@ The following example shows an example of a Java-based bean metadata that suppor public class AppConfig { /* - * Factory bean that creates the com.mongodb.MongoClient instance + * Factory bean that creates the com.mongodb.client.MongoClient instance */ public @Bean MongoClientFactoryBean mongo() { MongoClientFactoryBean mongo = new MongoClientFactoryBean(); @@ -214,12 +214,12 @@ public class AppConfig { ---- ==== -To access the `com.mongodb.MongoClient` object created by the `MongoClientFactoryBean` in other `@Configuration` classes or your own classes, use a `private @Autowired Mongo mongo;` field. +To access the `com.mongodb.client.MongoClient` object created by the `MongoClientFactoryBean` in other `@Configuration` classes or your own classes, use a `private @Autowired Mongo mongo;` field. [[mongo.mongo-xml-config]] === Registering a Mongo Instance by Using XML-based Metadata -While you can use Spring's traditional `` XML namespace to register an instance of `com.mongodb.MongoClient` with the container, the XML can be quite verbose, as it is general-purpose. XML namespaces are a better alternative to configuring commonly used objects, such as the Mongo instance. The mongo namespace lets you create a Mongo instance server location, replica-sets, and options. +While you can use Spring's traditional `` XML namespace to register an instance of `com.mongodb.client.MongoClient` with the container, the XML can be quite verbose, as it is general-purpose. XML namespaces are a better alternative to configuring commonly used objects, such as the Mongo instance. The mongo namespace lets you create a Mongo instance server location, replica-sets, and options. To use the Mongo namespace elements, you need to reference the Mongo schema, as follows: @@ -246,26 +246,22 @@ To use the Mongo namespace elements, you need to reference the Mongo schema, as ---- ==== -The following example shows a more advanced configuration with `MongoClientOptions` (note that these are not recommended values): +The following example shows a more advanced configuration with `MongoClientSettings` (note that these are not recommended values): -.XML schema to configure a com.mongodb.MongoClient object with MongoClientOptions +.XML schema to configure a `com.mongodb.client.MongoClient` object with `MongoClientSettings` ==== [source,xml] ---- - + @@ -274,18 +270,20 @@ The following example shows a more advanced configuration with `MongoClientOptio The following example shows a configuration using replica sets: -.XML schema to configure a `com.mongodb.MongoClient` object with Replica Sets +.XML schema to configure a `com.mongodb.client.MongoClient` object with Replica Sets ==== [source,xml] ---- - + + + ---- ==== [[mongo.mongo-db-factory]] === The MongoDbFactory Interface -While `com.mongodb.MongoClient` is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a `com.mongodb.client.MongoDatabase` object and access all the functionality of a specific MongoDB database instance. Spring provides the `org.springframework.data.mongodb.core.MongoDbFactory` interface, shown in the following listing, to bootstrap connectivity to the database: +While `com.mongodb.client.MongoClient` is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a `com.mongodb.client.MongoDatabase` object and access all the functionality of a specific MongoDB database instance. Spring provides the `org.springframework.data.mongodb.core.MongoDbFactory` interface, shown in the following listing, to bootstrap connectivity to the database: [source,java] ---- @@ -309,7 +307,7 @@ public class MongoApp { public static void main(String[] args) throws Exception { - MongoOperations mongoOps = new MongoTemplate(new SimpleMongoDbFactory(new MongoClient(), "database")); + MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDbFactory(MongoClients.create(), "database")); mongoOps.insert(new Person("Joe", 34)); @@ -320,7 +318,7 @@ public class MongoApp { } ---- -The code in bold highlights the use of `SimpleMongoDbFactory` and is the only difference between the listing shown in the <>. +The code in bold highlights the use of `SimpleMongoClientDbFactory` and is the only difference between the listing shown in the <>. NOTE: Use `SimpleMongoClientDbFactory` when choosing `com.mongodb.client.MongoClient` as the entrypoint of choice. @@ -335,7 +333,7 @@ To register a `MongoDbFactory` instance with the container, you write code much public class MongoConfiguration { public @Bean MongoDbFactory mongoDbFactory() { - return new SimpleMongoDbFactory(new MongoClient(), "database"); + return new SimpleMongoClientDbFactory(MongoClients.create(), "database"); } } ---- @@ -345,7 +343,7 @@ MongoDB Server generation 3 changed the authentication model when connecting to [source,java] ---- @Configuration -public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfiguration { +public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { @Override public String getDatabaseName() { @@ -355,24 +353,26 @@ public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfigur @Override @Bean public MongoClient mongoClient() { - return new MongoClient(singletonList(new ServerAddress("127.0.0.1", 27017)), - singletonList(MongoCredential.createCredential("name", "db", "pwd".toCharArray()))); + + MongoClientSettings settings = MongoClientSettings.builder() + .credential(MongoCredential.createCredential("name", "db", "pwd".toCharArray())) + .applyToClusterSettings(settings -> { + settings.hosts(singletonList(new ServerAddress("127.0.0.1", 27017))); + }) + .build(); + + return MongoClients.create(settings); } } ---- -In order to use authentication with XML-based configuration, use the `credentials` attribute on the `` element. +In order to use authentication with XML-based configuration, use the `credential` attribute on the `` element. NOTE: Username and password credentials used in XML-based configuration must be URL-encoded when these contain reserved characters, such as `:`, `%`, `@`, or `,`. The following example shows encoded credentials: `m0ng0@dmin:mo_res:bw6},Qsdxx@admin@database` -> `m0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database` See https://tools.ietf.org/html/rfc3986#section-2.2[section 2.2 of RFC 3986] for further details. -As of MongoDB java driver 3.7.0 there is an alternative entry point to `MongoClient` via the https://search.maven.org/beta/search?q=a:mongodb-driver-sync[mongodb-driver-sync] artifact. -`com.mongodb.client.MongoClient` is *not* compatible with `com.mongodb.MongoClient` and does not longer support -the legacy `DBObject` codec. Therefore, it cannot be used with `Querydsl` and requires a different configuration. -You can use `AbstractMongoClientConfiguration` to leverage the new `MongoClients` builder API. - [source,java] ---- @Configuration @@ -393,32 +393,27 @@ public class MongoClientConfiguration extends AbstractMongoClientConfiguration { [[mongo.mongo-db-factory-xml]] === Registering a `MongoDbFactory` Instance by Using XML-based Metadata -The `mongo` namespace provides a convenient way to create a `SimpleMongoDbFactory`, as compared to using the `` namespace, as shown in the following example: +The `mongo` namespace provides a convenient way to create a `SimpleMongoClientDbFactory`, as compared to using the `` namespace, as shown in the following example: [source,xml] ---- ---- -If you need to configure additional options on the `com.mongodb.MongoClient` instance that is used to create a `SimpleMongoDbFactory`, you can refer to an existing bean by using the `mongo-ref` attribute as shown in the following example. To show another common usage pattern, the following listing shows the use of a property placeholder, which lets you parametrize the configuration and the creation of a `MongoTemplate`: +If you need to configure additional options on the `com.mongodb.client.MongoClient` instance that is used to create a `SimpleMongoClientDbFactory`, you can refer to an existing bean by using the `mongo-ref` attribute as shown in the following example. To show another common usage pattern, the following listing shows the use of a property placeholder, which lets you parametrize the configuration and the creation of a `MongoTemplate`: [source,xml] ---- - + @@ -454,7 +449,7 @@ The next section contains an example of how to work with the `MongoTemplate` in You can use Java to create and register an instance of `MongoTemplate`, as the following example shows: -.Registering a `com.mongodb.MongoClient` object and enabling Spring's exception translation support +.Registering a `com.mongodb.client.MongoClient` object and enabling Spring's exception translation support ==== [source,java] ---- @@ -462,7 +457,7 @@ You can use Java to create and register an instance of `MongoTemplate`, as the f public class AppConfig { public @Bean MongoClient mongoClient() { - return new MongoClient("localhost"); + return MongoClients.create("mongodb://localhost:27017"); } public @Bean MongoTemplate mongoTemplate() { @@ -502,7 +497,7 @@ When in development, it is handy to either log or throw an exception if the `com [[mongo-template.writeconcern]] === `WriteConcern` -If it has not yet been specified through the driver at a higher level (such as `com.mongodb.MongoClient`), you can set the `com.mongodb.WriteConcern` property that the `MongoTemplate` uses for write operations. If the `WriteConcern` property is not set, it defaults to the one set in the MongoDB driver's DB or Collection setting. +If it has not yet been specified through the driver at a higher level (such as `com.mongodb.client.MongoClient`), you can set the `com.mongodb.WriteConcern` property that the `MongoTemplate` uses for write operations. If the `WriteConcern` property is not set, it defaults to the one set in the MongoDB driver's DB or Collection setting. [[mongo-template.writeconcernresolver]] === `WriteConcernResolver` @@ -589,7 +584,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import com.mongodb.client.MongoClients; @@ -701,7 +696,6 @@ MongoDB collections can contain documents that represent instances of a variety To achieve that, the `MappingMongoConverter` uses a `MongoTypeMapper` abstraction with `DefaultMongoTypeMapper` as its main implementation. Its default behavior to store the fully qualified classname under `_class` inside the document. Type hints are written for top-level documents as well as for every value (if it is a complex type and a subtype of the declared property type). The following example (with a JSON representation at the end) shows how the mapping works: - .Type mapping ==== [source,java] @@ -762,7 +756,7 @@ class CustomMongoTypeMapper extends DefaultMongoTypeMapper { [source,java] ---- @Configuration -class SampleMongoConfiguration extends AbstractMongoConfiguration { +class SampleMongoConfiguration extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { @@ -771,7 +765,7 @@ class SampleMongoConfiguration extends AbstractMongoConfiguration { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Bean @@ -790,7 +784,7 @@ class SampleMongoConfiguration extends AbstractMongoConfiguration { ---- ==== -Note that the preceding example extends the `AbstractMongoConfiguration` class and overrides the bean definition of the `MappingMongoConverter` where we configured our custom `MongoTypeMapper`. +Note that the preceding example extends the `AbstractMongoClientConfiguration` class and overrides the bean definition of the `MappingMongoConverter` where we configured our custom `MongoTypeMapper`. The following example shows how to use XML to configure a custom `MongoTypeMapper`: @@ -3282,7 +3276,7 @@ MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data ==== [source,java] ---- -class GridFsConfiguration extends AbstractMongoConfiguration { +class GridFsConfiguration extends AbstractMongoClientConfiguration { // … further configuration omitted diff --git a/src/main/asciidoc/reference/reactive-mongodb.adoc b/src/main/asciidoc/reference/reactive-mongodb.adoc index 3e999e6e36..ec4eb581e3 100644 --- a/src/main/asciidoc/reference/reactive-mongodb.adoc +++ b/src/main/asciidoc/reference/reactive-mongodb.adoc @@ -145,7 +145,7 @@ One of the first tasks when using MongoDB and Spring is to create a `com.mongodb The following example shows how to use Java-based bean metadata to register an instance of a `com.mongodb.reactivestreams.client.MongoClient`: -.Registering a com.mongodb.MongoClient object using Java based bean metadata +.Registering a `com.mongodb.reactivestreams.client.MongoClient` object using Java based bean metadata ==== [source,java] ---- @@ -168,7 +168,7 @@ An alternative is to register an instance of `com.mongodb.reactivestreams.client The following example shows Java-based bean metadata that supports exception translation on `@Repository` annotated classes: -.Registering a com.mongodb.MongoClient object using Spring's MongoClientFactoryBean and enabling Spring's exception translation support +.Registering a `com.mongodb.reactivestreams.client.MongoClient` object using Spring's MongoClientFactoryBean and enabling Spring's exception translation support ==== [source,java] ---- @@ -250,7 +250,7 @@ public class MongoApp { } ---- -The use of `SimpleMongoDbFactory` is the only difference between the listing shown in the <>. +The use of `SimpleReactiveMongoDatabaseFactory` is the only difference between the listing shown in the <>. [[mongo.reactive.mongo-db-factory-java]] === Registering a ReactiveMongoDatabaseFactory Instance by Using Java-based Metadata @@ -329,7 +329,7 @@ public class AppConfig { There are several overloaded constructors of `ReactiveMongoTemplate`, including: -* `ReactiveMongoTemplate(MongoClient mongo, String databaseName)`: Takes the `com.mongodb.MongoClient` object and the default database name to operate against. +* `ReactiveMongoTemplate(MongoClient mongo, String databaseName)`: Takes the `com.mongodb.reactivestreams.client.MongoClient` object and the default database name to operate against. * `ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory)`: Takes a `ReactiveMongoDatabaseFactory` object that encapsulated the `com.mongodb.reactivestreams.client.MongoClient` object and database name. * `ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory, MongoConverter mongoConverter)`: Adds a `MongoConverter` to use for mapping. diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc new file mode 100644 index 0000000000..0939983794 --- /dev/null +++ b/src/main/asciidoc/upgrading.adoc @@ -0,0 +1,123 @@ +[[upgrading]] += Upgrading from 2.x to 3.x + +Spring Data MongoDB 3.x requires the MongoDB Java Driver 4.x. + +The 4.0 MongoDB Java Driver does no longer support certain features that have already been deprecated in one of the last minor versions. +Some of the changes affect the initial setup configuration as well as compile/runtime features. We summarized the most typical changes one might encounter. + +== Dependency Changes + +Instead of the single artifact uber jar `mongo-java-driver`, imports are now split to include separate artifacts: + +* `org.mongodb:mongodb-driver-core` (required) +* `org.mongodb:mongodb-driver-sync` (optional) +* `org.mongodb:mongodb-driver-reactivestreams` (optional) + +== Java Configuration + +.Java API changes +|=== +Type | Comment + +| `MongoClientFactoryBean` +| Creates `com.mongodb.client.MongoClient` instead of `com.mongodb.MongoClient` + +Uses `MongoClientSettings` instead of `MongoClientOptions`. + +| `MongoDataIntegrityViolationException` +| Uses `WriteConcernResult` instead of `WriteResult`. + +| `BulkOperationException` +| Uses `MongoBulkWriteException` and `com.mongodb.bulk.BulkWriteError` instead of `BulkWriteException` and `com.mongodb.BulkWriteError` + +| `ReactiveMongoClientFactoryBean` +| Uses `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` + +| `ReactiveMongoClientSettingsFactoryBean` +| Now produces `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` +|=== + +.Removed Java API: +|=== +2.x | Replacement in 3.x | Comment + +| `MongoClientOptionsFactoryBean` +| `MongoClientSettingsFactoryBean` +| Creating a `com.mongodb.MongoClientSettings`. + +| `AbstractMongoConfiguration` +| `AbstractMongoClientConfiguration` + +(Available since 2.1) +| Using `com.mongodb.client.MongoClient`. + +| `MongoDbFactory#getLegacyDb()` +| - +| - + +| `SimpleMongoDbFactory` +| `SimpleMongoClientDbFactory` + +(Available since 2.1) +| + +| `MapReduceOptions#getOutputType()` +| `MapReduceOptions#getMapReduceAction()` +| Returns `MapReduceAction` instead of `MapReduceCommand.OutputType`. + +| `Meta\|Query` maxScan & snapshot +| +| +|=== + +== XML Namespace + +.Changed XML Namespace Elements and Attributes: +|=== +Element / Attribute | 2.x | 3.x + +| `` +| Used to create a `com.mongodb.MongoClient` +| Now exposes a `com.mongodb.client.MongoClient` + +| `` +| Was a comma delimited list of replica set members (host/port) +| Now defines the replica set name. + +Use `` instead + +| `` +| NONE, NORMAL, SAFE, FSYNC_SAFE, REPLICAS_SAFE, MAJORITY +| W1, W2, W3, UNAKNOWLEDGED, AKNOWLEDGED, JOURNALED, MAJORITY +|=== + +.Removed XML Namespace Elements and Attributes: +|=== +Element / Attribute | Replacement in 3.x | Comment + +| `` +| `` +| Referencing a `com.mongodb.client.MongoClient`. + +| `` +| `` +| Single authentication data instead of list. + +| `` +| `` +| See `com.mongodb.MongoClientSettings` for details. +|=== + +.New XML Namespace Elements and Attributes: +|=== +Element | Comment + +| `` +| Replacement for `` + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Namespace element for `com.mongodb.MongoClientSettings`. + +|=== From 2a3f8627035392f6100d13e054e93d4d927dc891 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 13 Dec 2019 08:54:57 +0100 Subject: [PATCH 0045/1381] DATAMONGO-2427 - Rename MongoDbFactory to MongoDatabaseFactory. Rename to follow MongoDB's naming scheme. Re-introduce deprecated MongoDbFactory to aid migration. Original pull request: #823. --- .../data/mongodb/MongoDatabaseFactory.java | 112 ++++++++ .../data/mongodb/MongoDatabaseUtils.java | 48 ++-- .../data/mongodb/MongoDbFactory.java | 85 +----- .../data/mongodb/MongoResourceHolder.java | 10 +- .../data/mongodb/MongoTransactionManager.java | 45 +-- .../mongodb/ReactiveMongoDatabaseFactory.java | 2 +- .../mongodb/ReactiveMongoResourceHolder.java | 4 +- .../AbstractMongoClientConfiguration.java | 10 +- .../mongodb/config/MongoDbFactoryParser.java | 4 +- .../mongodb/core/DefaultIndexOperations.java | 6 +- .../core/DefaultIndexOperationsProvider.java | 8 +- .../core/MongoDatabaseFactorySupport.java | 260 ++++++++++++++++++ .../mongodb/core/MongoDbFactorySupport.java | 223 +-------------- .../data/mongodb/core/MongoTemplate.java | 18 +- .../mongodb/core/ReactiveMongoTemplate.java | 4 +- .../SimpleMongoClientDatabaseFactory.java | 104 +++++++ .../core/SimpleMongoClientDbFactory.java | 37 +-- .../core/convert/DefaultDbRefResolver.java | 10 +- .../core/convert/MappingMongoConverter.java | 10 +- .../MongoPersistentEntityIndexCreator.java | 6 +- .../core/messaging/ChangeStreamTask.java | 2 +- .../core/messaging/SubscriptionRequest.java | 4 +- .../data/mongodb/gridfs/GridFsTemplate.java | 12 +- .../data/mongodb/config/spring-mongo-3.0.xsd | 18 +- .../mongodb/MongoDatabaseUtilsUnitTests.java | 2 +- .../MongoTransactionManagerUnitTests.java | 4 +- .../AbstractMongoConfigurationUnitTests.java | 4 +- .../MongoDbFactoryNoDatabaseRunningTests.java | 4 +- .../MongoDbFactoryParserIntegrationTests.java | 21 +- .../mongodb/config/MongoNamespaceTests.java | 16 +- .../mongodb/core/CountQueryUnitTests.java | 4 +- .../core/DefaultBulkOperationsUnitTests.java | 4 +- .../core/DefaultIndexOperationsUnitTests.java | 4 +- .../ExecutableFindOperationSupportTests.java | 2 +- ...ExecutableRemoveOperationSupportTests.java | 2 +- ...ExecutableUpdateOperationSupportTests.java | 2 +- .../data/mongodb/core/MongoTemplateTests.java | 4 +- .../core/MongoTemplateTransactionTests.java | 4 +- .../mongodb/core/MongoTemplateUnitTests.java | 4 +- .../core/MongoTemplateUpdateTests.java | 2 +- .../core/QueryCursorPreparerUnitTests.java | 4 +- .../ReactiveFindOperationSupportTests.java | 4 +- .../ReactiveRemoveOperationSupportTests.java | 4 +- .../ReactiveUpdateOperationSupportTests.java | 2 +- .../core/SessionBoundMongoTemplateTests.java | 7 +- .../SessionBoundMongoTemplateUnitTests.java | 6 +- ...eMongoClientDatabaseFactoryUnitTests.java} | 22 +- .../FilterExpressionUnitTests.java | 4 +- ...ExpressionTransformerIntegrationTests.java | 4 +- .../convert/CustomConvertersUnitTests.java | 4 +- .../DbRefMappingMongoConverterUnitTests.java | 4 +- .../DefaultDbRefResolverUnitTests.java | 4 +- .../convert/MappingMongoConverterTests.java | 7 +- .../convert/MongoExampleMapperUnitTests.java | 4 +- .../core/convert/QueryMapperUnitTests.java | 5 +- .../core/convert/UpdateMapperUnitTests.java | 4 +- .../core/index/IndexingIntegrationTests.java | 4 +- ...PersistentEntityIndexCreatorUnitTests.java | 4 +- .../core/mapreduce/MapReduceTests.java | 7 +- .../DefaultMessageListenerContainerTests.java | 8 +- .../GridFsTemplateIntegrationTests.java | 4 +- .../gridfs/ReactiveGridFsTemplateTests.java | 4 +- .../mongodb/performance/PerformanceTests.java | 6 +- .../ComplexIdRepositoryIntegrationTests.java | 3 +- .../PersonRepositoryTransactionalTests.java | 4 +- .../repository/cdi/MongoTemplateProducer.java | 6 +- ...RepositoriesRegistrarIntegrationTests.java | 4 +- .../query/AbstractMongoQueryUnitTests.java | 4 +- .../ConvertingParameterAccessorUnitTests.java | 4 +- .../query/MongoQueryCreatorUnitTests.java | 4 +- .../query/PartTreeMongoQueryUnitTests.java | 4 +- ...ongoPredicateExecutorIntegrationTests.java | 4 +- .../src/test/resources/geospatial.xml | 12 +- .../test/resources/gridfs/reactive-gridfs.xml | 2 +- .../src/test/resources/infrastructure.xml | 2 +- src/main/asciidoc/upgrading.adoc | 21 +- 76 files changed, 750 insertions(+), 575 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java rename spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/{SimpleMongoClientDbFactoryUnitTests.java => SimpleMongoClientDatabaseFactoryUnitTests.java} (79%) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java new file mode 100644 index 0000000000..846a527271 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java @@ -0,0 +1,112 @@ +/* + * Copyright 2011-2019 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 + * + * https://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; + +import org.bson.codecs.configuration.CodecRegistry; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; + +import com.mongodb.ClientSessionOptions; +import com.mongodb.client.ClientSession; +import com.mongodb.client.MongoDatabase; + +/** + * Interface for factories creating {@link MongoDatabase} instances. + * + * @author Mark Pollack + * @author Thomas Darimont + * @author Christoph Strobl + * @since 3.0 + */ +public interface MongoDatabaseFactory extends CodecRegistryProvider, MongoSessionProvider { + + /** + * Obtain a {@link MongoDatabase} from the underlying factory. + * + * @return never {@literal null}. + * @throws DataAccessException + */ + MongoDatabase getMongoDatabase() throws DataAccessException; + + /** + * Obtain a {@link MongoDatabase} instance to access the database with the given name. + * + * @param dbName + * @return never {@literal null}. + * @throws DataAccessException + */ + MongoDatabase getMongoDatabase(String dbName) throws DataAccessException; + + /** + * Exposes a shared {@link MongoExceptionTranslator}. + * + * @return will never be {@literal null}. + */ + PersistenceExceptionTranslator getExceptionTranslator(); + + /** + * Get the underlying {@link CodecRegistry} used by the MongoDB Java driver. + * + * @return never {@literal null}. + */ + @Override + default CodecRegistry getCodecRegistry() { + return getMongoDatabase().getCodecRegistry(); + } + + /** + * Obtain a {@link ClientSession} for given ClientSessionOptions. + * + * @param options must not be {@literal null}. + * @return never {@literal null}. + * @since 2.1 + */ + ClientSession getSession(ClientSessionOptions options); + + /** + * Obtain a {@link ClientSession} bound instance of {@link MongoDatabaseFactory} returning {@link MongoDatabase} + * instances that are aware and bound to a new session with given {@link ClientSessionOptions options}. + * + * @param options must not be {@literal null}. + * @return never {@literal null}. + * @since 2.1 + */ + default MongoDatabaseFactory withSession(ClientSessionOptions options) { + return withSession(getSession(options)); + } + + /** + * Obtain a {@link ClientSession} bound instance of {@link MongoDatabaseFactory} returning {@link MongoDatabase} + * instances that are aware and bound to the given session. + * + * @param session must not be {@literal null}. + * @return never {@literal null}. + * @since 2.1 + */ + MongoDatabaseFactory withSession(ClientSession session); + + /** + * Returns if the given {@link MongoDatabaseFactory} is bound to a {@link ClientSession} that has an + * {@link ClientSession#hasActiveTransaction() active transaction}. + * + * @return {@literal true} if there's an active transaction, {@literal false} otherwise. + * @since 2.1.3 + */ + default boolean isTransactionActive() { + return false; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index bd5df06688..2c7d3903cd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -27,7 +27,7 @@ import com.mongodb.client.MongoDatabase; /** - * Helper class for managing a {@link MongoDatabase} instances via {@link MongoDbFactory}. Used for obtaining + * Helper class for managing a {@link MongoDatabase} instances via {@link MongoDatabaseFactory}. Used for obtaining * {@link ClientSession session bound} resources, such as {@link MongoDatabase} and * {@link com.mongodb.client.MongoCollection} suitable for transactional usage. *

      @@ -41,65 +41,65 @@ public class MongoDatabaseUtils { /** - * Obtain the default {@link MongoDatabase database} form the given {@link MongoDbFactory factory} using + * Obtain the default {@link MongoDatabase database} form the given {@link MongoDatabaseFactory factory} using * {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}. *

      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * - * @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from. + * @param factory the {@link MongoDatabaseFactory} to get the {@link MongoDatabase} from. * @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}. */ - public static MongoDatabase getDatabase(MongoDbFactory factory) { + public static MongoDatabase getDatabase(MongoDatabaseFactory factory) { return doGetMongoDatabase(null, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION); } /** - * Obtain the default {@link MongoDatabase database} form the given {@link MongoDbFactory factory}. + * Obtain the default {@link MongoDatabase database} form the given {@link MongoDatabaseFactory factory}. *

      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * - * @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from. + * @param factory the {@link MongoDatabaseFactory} to get the {@link MongoDatabase} from. * @param sessionSynchronization the synchronization to use. Must not be {@literal null}. * @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}. */ - public static MongoDatabase getDatabase(MongoDbFactory factory, SessionSynchronization sessionSynchronization) { + public static MongoDatabase getDatabase(MongoDatabaseFactory factory, SessionSynchronization sessionSynchronization) { return doGetMongoDatabase(null, factory, sessionSynchronization); } /** - * Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDbFactory factory} using + * Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDatabaseFactory factory} using * {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}. *

      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * * @param dbName the name of the {@link MongoDatabase} to get. - * @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from. + * @param factory the {@link MongoDatabaseFactory} to get the {@link MongoDatabase} from. * @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}. */ - public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory) { + public static MongoDatabase getDatabase(String dbName, MongoDatabaseFactory factory) { return doGetMongoDatabase(dbName, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION); } /** - * Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDbFactory factory}. + * Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDatabaseFactory factory}. *

      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. - * + * * @param dbName the name of the {@link MongoDatabase} to get. - * @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from. + * @param factory the {@link MongoDatabaseFactory} to get the {@link MongoDatabase} from. * @param sessionSynchronization the synchronization to use. Must not be {@literal null}. * @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}. */ - public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory, + public static MongoDatabase getDatabase(String dbName, MongoDatabaseFactory factory, SessionSynchronization sessionSynchronization) { return doGetMongoDatabase(dbName, factory, sessionSynchronization); } - private static MongoDatabase doGetMongoDatabase(@Nullable String dbName, MongoDbFactory factory, + private static MongoDatabase doGetMongoDatabase(@Nullable String dbName, MongoDatabaseFactory factory, SessionSynchronization sessionSynchronization) { Assert.notNull(factory, "Factory must not be null!"); @@ -114,20 +114,21 @@ private static MongoDatabase doGetMongoDatabase(@Nullable String dbName, MongoDb return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } - MongoDbFactory factoryToUse = factory.withSession(session); + MongoDatabaseFactory factoryToUse = factory.withSession(session); return StringUtils.hasText(dbName) ? factoryToUse.getMongoDatabase(dbName) : factoryToUse.getMongoDatabase(); } /** - * Check if the {@link MongoDbFactory} is actually bound to a {@link ClientSession} that has an active transaction, or - * if a {@link TransactionSynchronization} has been registered for the {@link MongoDbFactory resource} and if the - * associated {@link ClientSession} has an {@link ClientSession#hasActiveTransaction() active transaction}. + * Check if the {@link MongoDatabaseFactory} is actually bound to a {@link ClientSession} that has an active + * transaction, or if a {@link TransactionSynchronization} has been registered for the {@link MongoDatabaseFactory + * resource} and if the associated {@link ClientSession} has an {@link ClientSession#hasActiveTransaction() active + * transaction}. * * @param dbFactory the resource to check transactions for. Must not be {@literal null}. * @return {@literal true} if the factory has an ongoing transaction. * @since 2.1.3 */ - public static boolean isTransactionActive(MongoDbFactory dbFactory) { + public static boolean isTransactionActive(MongoDatabaseFactory dbFactory) { if (dbFactory.isTransactionActive()) { return true; @@ -138,7 +139,8 @@ public static boolean isTransactionActive(MongoDbFactory dbFactory) { } @Nullable - private static ClientSession doGetSession(MongoDbFactory dbFactory, SessionSynchronization sessionSynchronization) { + private static ClientSession doGetSession(MongoDatabaseFactory dbFactory, + SessionSynchronization sessionSynchronization) { MongoResourceHolder resourceHolder = (MongoResourceHolder) TransactionSynchronizationManager.getResource(dbFactory); @@ -169,7 +171,7 @@ private static ClientSession doGetSession(MongoDbFactory dbFactory, SessionSynch return resourceHolder.getSession(); } - private static ClientSession createClientSession(MongoDbFactory dbFactory) { + private static ClientSession createClientSession(MongoDatabaseFactory dbFactory) { return dbFactory.getSession(ClientSessionOptions.builder().causallyConsistent(true).build()); } @@ -184,7 +186,7 @@ private static class MongoSessionSynchronization extends ResourceHolderSynchroni private final MongoResourceHolder resourceHolder; - MongoSessionSynchronization(MongoResourceHolder resourceHolder, MongoDbFactory dbFactory) { + MongoSessionSynchronization(MongoResourceHolder resourceHolder, MongoDatabaseFactory dbFactory) { super(resourceHolder, dbFactory); this.resourceHolder = resourceHolder; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index 116d3b1f19..97d2c7d0ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -15,13 +15,8 @@ */ package org.springframework.data.mongodb; -import org.bson.codecs.configuration.CodecRegistry; import org.springframework.dao.DataAccessException; -import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.core.MongoExceptionTranslator; -import com.mongodb.ClientSessionOptions; -import com.mongodb.client.ClientSession; import com.mongodb.client.MongoDatabase; /** @@ -30,8 +25,10 @@ * @author Mark Pollack * @author Thomas Darimont * @author Christoph Strobl + * @deprecated since 3.0, use {@link MongoDatabaseFactory} instead. */ -public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvider { +@Deprecated +public interface MongoDbFactory extends MongoDatabaseFactory { /** * Creates a default {@link MongoDatabase} instance. @@ -46,15 +43,7 @@ default MongoDatabase getDb() throws DataAccessException { } /** - * Obtain a {@link MongoDatabase} from the underlying factory. - * - * @return never {@literal null}. - * @throws DataAccessException - */ - MongoDatabase getMongoDatabase() throws DataAccessException; - - /** - * Creates a {@link MongoDatabase} instance to access the database with the given name. + * Obtain a {@link MongoDatabase} instance to access the database with the given name. * * @param dbName must not be {@literal null} or empty. * @return @@ -65,70 +54,4 @@ default MongoDatabase getDb() throws DataAccessException { default MongoDatabase getDb(String dbName) throws DataAccessException { return getMongoDatabase(dbName); } - - /** - * @param dbName - * @return never {@literal null}. - * @throws DataAccessException - */ - MongoDatabase getMongoDatabase(String dbName) throws DataAccessException; - - /** - * Exposes a shared {@link MongoExceptionTranslator}. - * - * @return will never be {@literal null}. - */ - PersistenceExceptionTranslator getExceptionTranslator(); - - /** - * Get the underlying {@link CodecRegistry} used by the MongoDB Java driver. - * - * @return never {@literal null}. - */ - @Override - default CodecRegistry getCodecRegistry() { - return getMongoDatabase().getCodecRegistry(); - } - - /** - * Obtain a {@link ClientSession} for given ClientSessionOptions. - * - * @param options must not be {@literal null}. - * @return never {@literal null}. - * @since 2.1 - */ - ClientSession getSession(ClientSessionOptions options); - - /** - * Obtain a {@link ClientSession} bound instance of {@link MongoDbFactory} returning {@link MongoDatabase} instances - * that are aware and bound to a new session with given {@link ClientSessionOptions options}. - * - * @param options must not be {@literal null}. - * @return never {@literal null}. - * @since 2.1 - */ - default MongoDbFactory withSession(ClientSessionOptions options) { - return withSession(getSession(options)); - } - - /** - * Obtain a {@link ClientSession} bound instance of {@link MongoDbFactory} returning {@link MongoDatabase} instances - * that are aware and bound to the given session. - * - * @param session must not be {@literal null}. - * @return never {@literal null}. - * @since 2.1 - */ - MongoDbFactory withSession(ClientSession session); - - /** - * Returns if the given {@link MongoDbFactory} is bound to a {@link ClientSession} that has an - * {@link ClientSession#hasActiveTransaction() active transaction}. - * - * @return {@literal true} if there's an active transaction, {@literal false} otherwise. - * @since 2.1.3 - */ - default boolean isTransactionActive() { - return false; - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java index 6ebd5d9518..c1b80f814f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java @@ -36,15 +36,15 @@ class MongoResourceHolder extends ResourceHolderSupport { private @Nullable ClientSession session; - private MongoDbFactory dbFactory; + private MongoDatabaseFactory dbFactory; /** * Create a new {@link MongoResourceHolder} for a given {@link ClientSession session}. * * @param session the associated {@link ClientSession}. Can be {@literal null}. - * @param dbFactory the associated {@link MongoDbFactory}. must not be {@literal null}. + * @param dbFactory the associated {@link MongoDatabaseFactory}. must not be {@literal null}. */ - MongoResourceHolder(@Nullable ClientSession session, MongoDbFactory dbFactory) { + MongoResourceHolder(@Nullable ClientSession session, MongoDatabaseFactory dbFactory) { this.session = session; this.dbFactory = dbFactory; @@ -75,9 +75,9 @@ ClientSession getRequiredSession() { } /** - * @return the associated {@link MongoDbFactory}. + * @return the associated {@link MongoDatabaseFactory}. */ - public MongoDbFactory getDbFactory() { + public MongoDatabaseFactory getDbFactory() { return dbFactory; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java index d4f333a043..b0c8d640f7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java @@ -36,17 +36,18 @@ /** * A {@link org.springframework.transaction.PlatformTransactionManager} implementation that manages - * {@link ClientSession} based transactions for a single {@link MongoDbFactory}. + * {@link ClientSession} based transactions for a single {@link MongoDatabaseFactory}. *

      - * Binds a {@link ClientSession} from the specified {@link MongoDbFactory} to the thread. + * Binds a {@link ClientSession} from the specified {@link MongoDatabaseFactory} to the thread. *

      * {@link TransactionDefinition#isReadOnly() Readonly} transactions operate on a {@link ClientSession} and enable causal * consistency, and also {@link ClientSession#startTransaction() start}, {@link ClientSession#commitTransaction() * commit} or {@link ClientSession#abortTransaction() abort} a transaction. *

      * Application code is required to retrieve the {@link com.mongodb.client.MongoDatabase} via - * {@link MongoDatabaseUtils#getDatabase(MongoDbFactory)} instead of a standard {@link MongoDbFactory#getMongoDatabase()} call. - * Spring classes such as {@link org.springframework.data.mongodb.core.MongoTemplate} use this strategy implicitly. + * {@link MongoDatabaseUtils#getDatabase(MongoDatabaseFactory)} instead of a standard + * {@link MongoDatabaseFactory#getMongoDatabase()} call. Spring classes such as + * {@link org.springframework.data.mongodb.core.MongoTemplate} use this strategy implicitly. *

      * By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. One may override * {@link #doCommit(MongoTransactionObject)} to implement the @@ -58,46 +59,46 @@ * @currentRead Shadow's Edge - Brent Weeks * @since 2.1 * @see MongoDB Transaction Documentation - * @see MongoDatabaseUtils#getDatabase(MongoDbFactory, SessionSynchronization) + * @see MongoDatabaseUtils#getDatabase(MongoDatabaseFactory, SessionSynchronization) */ public class MongoTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean { - private @Nullable MongoDbFactory dbFactory; + private @Nullable MongoDatabaseFactory dbFactory; private @Nullable TransactionOptions options; /** * Create a new {@link MongoTransactionManager} for bean-style usage. *

      - * Note:The {@link MongoDbFactory db factory} has to be {@link #setDbFactory(MongoDbFactory) set} - * before using the instance. Use this constructor to prepare a {@link MongoTransactionManager} via a - * {@link org.springframework.beans.factory.BeanFactory}. + * Note:The {@link MongoDatabaseFactory db factory} has to be + * {@link #setDbFactory(MongoDatabaseFactory) set} before using the instance. Use this constructor to prepare a + * {@link MongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}. *

      * Optionally it is possible to set default {@link TransactionOptions transaction options} defining * {@link com.mongodb.ReadConcern} and {@link com.mongodb.WriteConcern}. * - * @see #setDbFactory(MongoDbFactory) + * @see #setDbFactory(MongoDatabaseFactory) * @see #setTransactionSynchronization(int) */ public MongoTransactionManager() {} /** - * Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDbFactory}. + * Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDatabaseFactory}. * * @param dbFactory must not be {@literal null}. */ - public MongoTransactionManager(MongoDbFactory dbFactory) { + public MongoTransactionManager(MongoDatabaseFactory dbFactory) { this(dbFactory, null); } /** - * Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDbFactory} applying the - * given {@link TransactionOptions options}, if present, when starting a new transaction. + * Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDatabaseFactory} + * applying the given {@link TransactionOptions options}, if present, when starting a new transaction. * * @param dbFactory must not be {@literal null}. * @param options can be {@literal null}. */ - public MongoTransactionManager(MongoDbFactory dbFactory, @Nullable TransactionOptions options) { + public MongoTransactionManager(MongoDatabaseFactory dbFactory, @Nullable TransactionOptions options) { Assert.notNull(dbFactory, "DbFactory must not be null!"); @@ -295,11 +296,11 @@ protected void doCleanupAfterCompletion(Object transaction) { } /** - * Set the {@link MongoDbFactory} that this instance should manage transactions for. + * Set the {@link MongoDatabaseFactory} that this instance should manage transactions for. * * @param dbFactory must not be {@literal null}. */ - public void setDbFactory(MongoDbFactory dbFactory) { + public void setDbFactory(MongoDatabaseFactory dbFactory) { Assert.notNull(dbFactory, "DbFactory must not be null!"); this.dbFactory = dbFactory; @@ -315,12 +316,12 @@ public void setOptions(@Nullable TransactionOptions options) { } /** - * Get the {@link MongoDbFactory} that this instance manages transactions for. + * Get the {@link MongoDatabaseFactory} that this instance manages transactions for. * * @return can be {@literal null}. */ @Nullable - public MongoDbFactory getDbFactory() { + public MongoDatabaseFactory getDbFactory() { return dbFactory; } @@ -329,7 +330,7 @@ public MongoDbFactory getDbFactory() { * @see org.springframework.transaction.support.ResourceTransactionManager#getResourceFactory() */ @Override - public MongoDbFactory getResourceFactory() { + public MongoDatabaseFactory getResourceFactory() { return getRequiredDbFactory(); } @@ -344,7 +345,7 @@ public void afterPropertiesSet() { private MongoResourceHolder newResourceHolder(TransactionDefinition definition, ClientSessionOptions options) { - MongoDbFactory dbFactory = getResourceFactory(); + MongoDatabaseFactory dbFactory = getResourceFactory(); MongoResourceHolder resourceHolder = new MongoResourceHolder(dbFactory.getSession(options), dbFactory); resourceHolder.setTimeoutIfNotDefaulted(determineTimeout(definition)); @@ -355,7 +356,7 @@ private MongoResourceHolder newResourceHolder(TransactionDefinition definition, /** * @throws IllegalStateException if {@link #dbFactory} is {@literal null}. */ - private MongoDbFactory getRequiredDbFactory() { + private MongoDatabaseFactory getRequiredDbFactory() { Assert.state(dbFactory != null, "MongoTransactionManager operates upon a MongoDbFactory. Did you forget to provide one? It's required."); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java index 601582702a..05932f7e00 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java @@ -44,7 +44,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { MongoDatabase getMongoDatabase() throws DataAccessException; /** - * Creates a {@link MongoDatabase} instance to access the database with the given name. + * Obtain a {@link MongoDatabase} instance to access the database with the given name. * * @param dbName must not be {@literal null} or empty. * @return diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java index fd16e408ed..34301bdc6f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java @@ -42,7 +42,7 @@ class ReactiveMongoResourceHolder extends ResourceHolderSupport { * Create a new {@link ReactiveMongoResourceHolder} for a given {@link ClientSession session}. * * @param session the associated {@link ClientSession}. Can be {@literal null}. - * @param databaseFactory the associated {@link MongoDbFactory}. must not be {@literal null}. + * @param databaseFactory the associated {@link MongoDatabaseFactory}. must not be {@literal null}. */ ReactiveMongoResourceHolder(@Nullable ClientSession session, ReactiveMongoDatabaseFactory databaseFactory) { @@ -99,7 +99,7 @@ boolean hasSession() { * If the {@link ReactiveMongoResourceHolder} is {@link #hasSession() not already associated} with a * {@link ClientSession} the given value is {@link #setSession(ClientSession) set} and returned, otherwise the current * bound session is returned. - * + * * @param session * @return */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index cb04fe7beb..cce5714985 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -17,9 +17,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -57,7 +57,7 @@ public MongoTemplate mongoTemplate() throws Exception { } /** - * Creates a {@link org.springframework.data.mongodb.core.SimpleMongoDbFactory;} to be used by the + * Creates a {@link org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory} to be used by the * {@link MongoTemplate}. Will use the {@link MongoClient} instance configured in {@link #mongoClient()}. * * @see #mongoClient() @@ -65,8 +65,8 @@ public MongoTemplate mongoTemplate() throws Exception { * @return */ @Bean - public MongoDbFactory mongoDbFactory() { - return new SimpleMongoClientDbFactory(mongoClient(), getDatabaseName()); + public MongoDatabaseFactory mongoDbFactory() { + return new SimpleMongoClientDatabaseFactory(mongoClient(), getDatabaseName()); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java index 677561c0d1..c929b5b3a6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java @@ -32,7 +32,7 @@ import org.springframework.beans.factory.xml.ParserContext; import org.springframework.data.config.BeanComponentDefinitionBuilder; import org.springframework.data.mongodb.core.MongoClientFactoryBean; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import org.w3c.dom.Element; @@ -83,7 +83,7 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa // Common setup BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder - .genericBeanDefinition(SimpleMongoClientDbFactory.class); + .genericBeanDefinition(SimpleMongoClientDatabaseFactory.class); setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern"); BeanDefinition mongoUri = getConnectionString(element, parserContext); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java index 879c69fa29..62ad1f46ee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java @@ -21,7 +21,7 @@ import org.bson.Document; import org.springframework.dao.DataAccessException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.IndexDefinition; import org.springframework.data.mongodb.core.index.IndexInfo; @@ -64,7 +64,7 @@ public class DefaultIndexOperations implements IndexOperations { * {@link DefaultIndexOperations#DefaultIndexOperations(MongoOperations, String, Class)}. */ @Deprecated - public DefaultIndexOperations(MongoDbFactory mongoDbFactory, String collectionName, QueryMapper queryMapper) { + public DefaultIndexOperations(MongoDatabaseFactory mongoDbFactory, String collectionName, QueryMapper queryMapper) { this(mongoDbFactory, collectionName, queryMapper, null); } @@ -80,7 +80,7 @@ public DefaultIndexOperations(MongoDbFactory mongoDbFactory, String collectionNa * {@link DefaultIndexOperations#DefaultIndexOperations(MongoOperations, String, Class)}. */ @Deprecated - public DefaultIndexOperations(MongoDbFactory mongoDbFactory, String collectionName, QueryMapper queryMapper, + public DefaultIndexOperations(MongoDatabaseFactory mongoDbFactory, String collectionName, QueryMapper queryMapper, @Nullable Class type) { Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!"); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java index f7a0a1658f..3888b0549b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java @@ -15,13 +15,13 @@ */ package org.springframework.data.mongodb.core; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.index.IndexOperationsProvider; /** - * {@link IndexOperationsProvider} to obtain {@link IndexOperations} from a given {@link MongoDbFactory}. + * {@link IndexOperationsProvider} to obtain {@link IndexOperations} from a given {@link MongoDatabaseFactory}. * * @author Mark Paluch * @author Christoph Strobl @@ -29,14 +29,14 @@ */ class DefaultIndexOperationsProvider implements IndexOperationsProvider { - private final MongoDbFactory mongoDbFactory; + private final MongoDatabaseFactory mongoDbFactory; private final QueryMapper mapper; /** * @param mongoDbFactory must not be {@literal null}. * @param mapper must not be {@literal null}. */ - DefaultIndexOperationsProvider(MongoDbFactory mongoDbFactory, QueryMapper mapper) { + DefaultIndexOperationsProvider(MongoDatabaseFactory mongoDbFactory, QueryMapper mapper) { this.mongoDbFactory = mongoDbFactory; this.mapper = mapper; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java new file mode 100644 index 0000000000..60f1ed56a9 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java @@ -0,0 +1,260 @@ +/* + * Copyright 2018-2019 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 + * + * https://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 lombok.Value; + +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.SessionAwareMethodInterceptor; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +import com.mongodb.ClientSessionOptions; +import com.mongodb.WriteConcern; +import com.mongodb.client.ClientSession; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; + +/** + * Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as + * database name and exception translator. + *

      + * Not intended to be used directly. + * + * @author Christoph Strobl + * @author Mark Paluch + * @param Client type. + * @since 3.0 + * @see SimpleMongoClientDatabaseFactory + */ +public abstract class MongoDatabaseFactorySupport implements MongoDatabaseFactory { + + private final C mongoClient; + private final String databaseName; + private final boolean mongoInstanceCreated; + private final PersistenceExceptionTranslator exceptionTranslator; + + private @Nullable WriteConcern writeConcern; + + /** + * Create a new {@link MongoDatabaseFactorySupport} object given {@code mongoClient}, {@code databaseName}, + * {@code mongoInstanceCreated} and {@link PersistenceExceptionTranslator}. + * + * @param mongoClient must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. + * @param mongoInstanceCreated {@literal true} if the client instance was created by a subclass of + * {@link MongoDatabaseFactorySupport} to close the client on {@link #destroy()}. + * @param exceptionTranslator must not be {@literal null}. + */ + protected MongoDatabaseFactorySupport(C mongoClient, String databaseName, boolean mongoInstanceCreated, + PersistenceExceptionTranslator exceptionTranslator) { + + Assert.notNull(mongoClient, "MongoClient must not be null!"); + Assert.hasText(databaseName, "Database name must not be empty!"); + Assert.isTrue(databaseName.matches("[^/\\\\.$\"\\s]+"), + "Database name must not contain slashes, dots, spaces, quotes, or dollar signs!"); + + this.mongoClient = mongoClient; + this.databaseName = databaseName; + this.mongoInstanceCreated = mongoInstanceCreated; + this.exceptionTranslator = exceptionTranslator; + } + + /** + * Configures the {@link WriteConcern} to be used on the {@link MongoDatabase} instance being created. + * + * @param writeConcern the writeConcern to set + */ + public void setWriteConcern(WriteConcern writeConcern) { + this.writeConcern = writeConcern; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() + */ + public MongoDatabase getMongoDatabase() throws DataAccessException { + return getMongoDatabase(getDefaultDatabaseName()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) + */ + @Override + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { + + Assert.hasText(dbName, "Database name must not be empty!"); + + MongoDatabase db = doGetMongoDatabase(dbName); + + if (writeConcern == null) { + return db; + } + + return db.withWriteConcern(writeConcern); + } + + /** + * Get the actual {@link MongoDatabase} from the client. + * + * @param dbName must not be {@literal null} or empty. + * @return + */ + protected abstract MongoDatabase doGetMongoDatabase(String dbName); + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + public void destroy() throws Exception { + if (mongoInstanceCreated) { + closeClient(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getExceptionTranslator() + */ + public PersistenceExceptionTranslator getExceptionTranslator() { + return this.exceptionTranslator; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#withSession(com.mongodb.session.Session) + */ + public MongoDatabaseFactory withSession(ClientSession session) { + return new MongoDatabaseFactorySupport.ClientSessionBoundMongoDbFactory(session, this); + } + + /** + * Close the client instance. + */ + protected abstract void closeClient(); + + /** + * @return the Mongo client object. + */ + protected C getMongoClient() { + return mongoClient; + } + + /** + * @return the database name. + */ + protected String getDefaultDatabaseName() { + return databaseName; + } + + /** + * {@link ClientSession} bound {@link MongoDatabaseFactory} decorating the database with a + * {@link SessionAwareMethodInterceptor}. + * + * @author Christoph Strobl + * @since 2.1 + */ + @Value + static class ClientSessionBoundMongoDbFactory implements MongoDatabaseFactory { + + ClientSession session; + MongoDatabaseFactory delegate; + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() + */ + @Override + public MongoDatabase getMongoDatabase() throws DataAccessException { + return proxyMongoDatabase(delegate.getMongoDatabase()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) + */ + @Override + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { + return proxyMongoDatabase(delegate.getMongoDatabase(dbName)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getExceptionTranslator() + */ + @Override + public PersistenceExceptionTranslator getExceptionTranslator() { + return delegate.getExceptionTranslator(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) + */ + @Override + public ClientSession getSession(ClientSessionOptions options) { + return delegate.getSession(options); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#withSession(com.mongodb.session.ClientSession) + */ + @Override + public MongoDatabaseFactory withSession(ClientSession session) { + return delegate.withSession(session); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#isTransactionActive() + */ + @Override + public boolean isTransactionActive() { + return session != null && session.hasActiveTransaction(); + } + + private MongoDatabase proxyMongoDatabase(MongoDatabase database) { + return createProxyInstance(session, database, MongoDatabase.class); + } + + private MongoDatabase proxyDatabase(com.mongodb.session.ClientSession session, MongoDatabase database) { + return createProxyInstance(session, database, MongoDatabase.class); + } + + private MongoCollection proxyCollection(com.mongodb.session.ClientSession session, + MongoCollection collection) { + return createProxyInstance(session, collection, MongoCollection.class); + } + + private T createProxyInstance(com.mongodb.session.ClientSession session, T target, Class targetType) { + + ProxyFactory factory = new ProxyFactory(); + factory.setTarget(target); + factory.setInterfaces(targetType); + factory.setOpaque(true); + + factory.addAdvice(new SessionAwareMethodInterceptor<>(session, target, ClientSession.class, MongoDatabase.class, + this::proxyDatabase, MongoCollection.class, this::proxyCollection)); + + return targetType.cast(factory.getProxy()); + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index b14518b108..f85dd8e1fd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -15,21 +15,7 @@ */ package org.springframework.data.mongodb.core; -import lombok.Value; - -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.SessionAwareMethodInterceptor; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -import com.mongodb.ClientSessionOptions; -import com.mongodb.WriteConcern; -import com.mongodb.client.ClientSession; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; /** * Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as @@ -41,21 +27,16 @@ * @author Mark Paluch * @param Client type. * @since 2.1 - * @see SimpleMongoClientDbFactory + * @see SimpleMongoClientDatabaseFactory + * @deprecated since 3.0, use {@link MongoDatabaseFactorySupport} instead. */ -public abstract class MongoDbFactorySupport implements MongoDbFactory { - - private final C mongoClient; - private final String databaseName; - private final boolean mongoInstanceCreated; - private final PersistenceExceptionTranslator exceptionTranslator; - - private @Nullable WriteConcern writeConcern; +@Deprecated +public abstract class MongoDbFactorySupport extends MongoDatabaseFactorySupport { /** * Create a new {@link MongoDbFactorySupport} object given {@code mongoClient}, {@code databaseName}, * {@code mongoInstanceCreated} and {@link PersistenceExceptionTranslator}. - * + * * @param mongoClient must not be {@literal null}. * @param databaseName must not be {@literal null} or empty. * @param mongoInstanceCreated {@literal true} if the client instance was created by a subclass of @@ -64,198 +45,6 @@ public abstract class MongoDbFactorySupport implements MongoDbFactory { */ protected MongoDbFactorySupport(C mongoClient, String databaseName, boolean mongoInstanceCreated, PersistenceExceptionTranslator exceptionTranslator) { - - Assert.notNull(mongoClient, "MongoClient must not be null!"); - Assert.hasText(databaseName, "Database name must not be empty!"); - Assert.isTrue(databaseName.matches("[^/\\\\.$\"\\s]+"), - "Database name must not contain slashes, dots, spaces, quotes, or dollar signs!"); - - this.mongoClient = mongoClient; - this.databaseName = databaseName; - this.mongoInstanceCreated = mongoInstanceCreated; - this.exceptionTranslator = exceptionTranslator; + super(mongoClient, databaseName, mongoInstanceCreated, exceptionTranslator); } - - /** - * Configures the {@link WriteConcern} to be used on the {@link MongoDatabase} instance being created. - * - * @param writeConcern the writeConcern to set - */ - public void setWriteConcern(WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() - */ - public MongoDatabase getMongoDatabase() throws DataAccessException { - return getMongoDatabase(getDefaultDatabaseName()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) - */ - @Override - public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { - - Assert.hasText(dbName, "Database name must not be empty!"); - - MongoDatabase db = doGetMongoDatabase(dbName); - - if (writeConcern == null) { - return db; - } - - return db.withWriteConcern(writeConcern); - } - - /** - * Get the actual {@link MongoDatabase} from the client. - * - * @param dbName must not be {@literal null} or empty. - * @return - */ - protected abstract MongoDatabase doGetMongoDatabase(String dbName); - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.DisposableBean#destroy() - */ - public void destroy() throws Exception { - if (mongoInstanceCreated) { - closeClient(); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getExceptionTranslator() - */ - public PersistenceExceptionTranslator getExceptionTranslator() { - return this.exceptionTranslator; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#withSession(com.mongodb.session.Session) - */ - public MongoDbFactory withSession(ClientSession session) { - return new MongoDbFactorySupport.ClientSessionBoundMongoDbFactory(session, this); - } - - /** - * Close the client instance. - */ - protected abstract void closeClient(); - - /** - * @return the Mongo client object. - */ - protected C getMongoClient() { - return mongoClient; - } - - /** - * @return the database name. - */ - protected String getDefaultDatabaseName() { - return databaseName; - } - - /** - * {@link ClientSession} bound {@link MongoDbFactory} decorating the database with a - * {@link SessionAwareMethodInterceptor}. - * - * @author Christoph Strobl - * @since 2.1 - */ - @Value - static class ClientSessionBoundMongoDbFactory implements MongoDbFactory { - - ClientSession session; - MongoDbFactory delegate; - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() - */ - @Override - public MongoDatabase getMongoDatabase() throws DataAccessException { - return proxyMongoDatabase(delegate.getMongoDatabase()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) - */ - @Override - public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { - return proxyMongoDatabase(delegate.getMongoDatabase(dbName)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getExceptionTranslator() - */ - @Override - public PersistenceExceptionTranslator getExceptionTranslator() { - return delegate.getExceptionTranslator(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) - */ - @Override - public ClientSession getSession(ClientSessionOptions options) { - return delegate.getSession(options); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#withSession(com.mongodb.session.ClientSession) - */ - @Override - public MongoDbFactory withSession(ClientSession session) { - return delegate.withSession(session); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#isTransactionActive() - */ - @Override - public boolean isTransactionActive() { - return session != null && session.hasActiveTransaction(); - } - - private MongoDatabase proxyMongoDatabase(MongoDatabase database) { - return createProxyInstance(session, database, MongoDatabase.class); - } - - private MongoDatabase proxyDatabase(com.mongodb.session.ClientSession session, MongoDatabase database) { - return createProxyInstance(session, database, MongoDatabase.class); - } - - private MongoCollection proxyCollection(com.mongodb.session.ClientSession session, - MongoCollection collection) { - return createProxyInstance(session, collection, MongoCollection.class); - } - - private T createProxyInstance(com.mongodb.session.ClientSession session, T target, Class targetType) { - - ProxyFactory factory = new ProxyFactory(); - factory.setTarget(target); - factory.setInterfaces(targetType); - factory.setOpaque(true); - - factory.addAdvice(new SessionAwareMethodInterceptor<>(session, target, ClientSession.class, MongoDatabase.class, - this::proxyDatabase, MongoCollection.class, this::proxyCollection)); - - return targetType.cast(factory.getProxy()); - } - } - } 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 a795cb5e8e..cd441ae248 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 @@ -58,7 +58,7 @@ import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.MongoDatabaseUtils; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.SessionSynchronization; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; @@ -186,7 +186,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, private final MongoConverter mongoConverter; private final MappingContext, MongoPersistentProperty> mappingContext; - private final MongoDbFactory mongoDbFactory; + private final MongoDatabaseFactory mongoDbFactory; private final PersistenceExceptionTranslator exceptionTranslator; private final QueryMapper queryMapper; private final UpdateMapper updateMapper; @@ -214,7 +214,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * @since 2.1 */ public MongoTemplate(com.mongodb.client.MongoClient mongoClient, String databaseName) { - this(new SimpleMongoClientDbFactory(mongoClient, databaseName), (MongoConverter) null); + this(new SimpleMongoClientDatabaseFactory(mongoClient, databaseName), (MongoConverter) null); } /** @@ -222,7 +222,7 @@ public MongoTemplate(com.mongodb.client.MongoClient mongoClient, String database * * @param mongoDbFactory must not be {@literal null}. */ - public MongoTemplate(MongoDbFactory mongoDbFactory) { + public MongoTemplate(MongoDatabaseFactory mongoDbFactory) { this(mongoDbFactory, (MongoConverter) null); } @@ -232,7 +232,7 @@ public MongoTemplate(MongoDbFactory mongoDbFactory) { * @param mongoDbFactory must not be {@literal null}. * @param mongoConverter */ - public MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mongoConverter) { + public MongoTemplate(MongoDatabaseFactory mongoDbFactory, @Nullable MongoConverter mongoConverter) { Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!"); @@ -262,7 +262,7 @@ public MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mon } } - private MongoTemplate(MongoDbFactory dbFactory, MongoTemplate that) { + private MongoTemplate(MongoDatabaseFactory dbFactory, MongoTemplate that) { this.mongoDbFactory = dbFactory; this.exceptionTranslator = that.exceptionTranslator; @@ -297,7 +297,7 @@ public void setWriteResultChecking(@Nullable WriteResultChecking resultChecking) /** * Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern} - * configured on the {@link MongoDbFactory} will apply. + * configured on the {@link MongoDatabaseFactory} will apply. * * @param writeConcern */ @@ -2858,7 +2858,7 @@ private MongoPersistentEntity getPersistentEntity(@Nullable Class type) { return type != null ? mappingContext.getPersistentEntity(type) : null; } - private static MongoConverter getDefaultMongoConverter(MongoDbFactory factory) { + private static MongoConverter getDefaultMongoConverter(MongoDatabaseFactory factory) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); MongoCustomConversions conversions = new MongoCustomConversions(Collections.emptyList()); @@ -3448,7 +3448,7 @@ public void close() { } } - public MongoDbFactory getMongoDbFactory() { + public MongoDatabaseFactory getMongoDbFactory() { return mongoDbFactory; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 203e622e8b..3993105fc6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -62,7 +62,7 @@ import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.MappingContextEvent; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.ReactiveMongoDatabaseUtils; import org.springframework.data.mongodb.SessionSynchronization; @@ -320,7 +320,7 @@ public void setWriteResultChecking(@Nullable WriteResultChecking resultChecking) /** * Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern} - * configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no + * configured on the {@link MongoDatabaseFactory} will apply. If you configured a {@link Mongo} instance no * {@link WriteConcern} will be used. * * @param writeConcern can be {@literal null}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java new file mode 100644 index 0000000000..b665128a0c --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018-2019 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 + * + * https://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 org.springframework.beans.factory.DisposableBean; + +import com.mongodb.ClientSessionOptions; +import com.mongodb.ConnectionString; +import com.mongodb.client.ClientSession; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; + +/** + * Factory to create {@link MongoDatabase} instances from a {@link MongoClient} instance. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class SimpleMongoClientDatabaseFactory extends MongoDatabaseFactorySupport + implements DisposableBean { + + /** + * Creates a new {@link SimpleMongoClientDatabaseFactory} instance for the given {@code connectionString}. + * + * @param connectionString connection coordinates for a database connection. Must contain a database name and must not + * be {@literal null} or empty. + * @see MongoDB Connection String reference + */ + public SimpleMongoClientDatabaseFactory(String connectionString) { + this(new ConnectionString(connectionString)); + } + + /** + * Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. + * + * @param connectionString connection coordinates for a database connection. Must contain also a database name and not + * be {@literal null}. + */ + public SimpleMongoClientDatabaseFactory(ConnectionString connectionString) { + this(MongoClients.create(connectionString), connectionString.getDatabase(), true); + } + + /** + * Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. + * + * @param mongoClient must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. + */ + public SimpleMongoClientDatabaseFactory(MongoClient mongoClient, String databaseName) { + this(mongoClient, databaseName, false); + } + + /** + * Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. + * + * @param mongoClient must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. + * @param mongoInstanceCreated + */ + SimpleMongoClientDatabaseFactory(MongoClient mongoClient, String databaseName, boolean mongoInstanceCreated) { + super(mongoClient, databaseName, mongoInstanceCreated, new MongoExceptionTranslator()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) + */ + @Override + public ClientSession getSession(ClientSessionOptions options) { + return getMongoClient().startSession(options); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#closeClient() + */ + @Override + protected void closeClient() { + getMongoClient().close(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#doGetMongoDatabase(java.lang.String) + */ + @Override + protected MongoDatabase doGetMongoDatabase(String dbName) { + return getMongoClient().getDatabase(dbName); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java index 2743f8abef..08c69af2b0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java @@ -15,11 +15,7 @@ */ package org.springframework.data.mongodb.core; -import org.springframework.beans.factory.DisposableBean; - -import com.mongodb.ClientSessionOptions; import com.mongodb.ConnectionString; -import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoDatabase; @@ -29,8 +25,10 @@ * * @author Christoph Strobl * @since 2.1 + * @deprecated since 3.0, use {@link SimpleMongoClientDatabaseFactory} instead. */ -public class SimpleMongoClientDbFactory extends MongoDbFactorySupport implements DisposableBean { +@Deprecated +public class SimpleMongoClientDbFactory extends SimpleMongoClientDatabaseFactory { /** * Creates a new {@link SimpleMongoClientDbFactory} instance for the given {@code connectionString}. @@ -71,33 +69,6 @@ public SimpleMongoClientDbFactory(MongoClient mongoClient, String databaseName) * @param mongoInstanceCreated */ private SimpleMongoClientDbFactory(MongoClient mongoClient, String databaseName, boolean mongoInstanceCreated) { - super(mongoClient, databaseName, mongoInstanceCreated, new MongoExceptionTranslator()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) - */ - @Override - public ClientSession getSession(ClientSessionOptions options) { - return getMongoClient().startSession(options); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#closeClient() - */ - @Override - protected void closeClient() { - getMongoClient().close(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#doGetMongoDatabase(java.lang.String) - */ - @Override - protected MongoDatabase doGetMongoDatabase(String dbName) { - return getMongoClient().getDatabase(dbName); + super(mongoClient, databaseName, mongoInstanceCreated); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 73281a2477..8e4baa5fd8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -44,7 +44,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.LazyLoadingException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisStd; @@ -70,16 +70,16 @@ public class DefaultDbRefResolver implements DbRefResolver { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultDbRefResolver.class); - private final MongoDbFactory mongoDbFactory; + private final MongoDatabaseFactory mongoDbFactory; private final PersistenceExceptionTranslator exceptionTranslator; private final ObjenesisStd objenesis; /** - * Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}. + * Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDatabaseFactory}. * * @param mongoDbFactory must not be {@literal null}. */ - public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) { + public DefaultDbRefResolver(MongoDatabaseFactory mongoDbFactory) { Assert.notNull(mongoDbFactory, "MongoDbFactory translator must not be null!"); @@ -497,7 +497,7 @@ private synchronized Object resolve() { */ protected MongoCollection getCollection(DBRef dbref) { - return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getDb(dbref.getDatabaseName()) + return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getMongoDatabase(dbref.getDatabaseName()) : mongoDbFactory.getMongoDatabase()).getCollection(dbref.getCollectionName(), Document.class); } } 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 05c4c0b5d1..f189938d11 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 @@ -60,7 +60,7 @@ import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider; import org.springframework.data.mongodb.CodecRegistryProvider; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent; @@ -135,14 +135,14 @@ public MappingMongoConverter(DbRefResolver dbRefResolver, } /** - * Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}. + * Creates a new {@link MappingMongoConverter} given the new {@link MongoDatabaseFactory} and {@link MappingContext}. * * @deprecated use the constructor taking a {@link DbRefResolver} instead. * @param mongoDbFactory must not be {@literal null}. * @param mappingContext must not be {@literal null}. */ @Deprecated - public MappingMongoConverter(MongoDbFactory mongoDbFactory, + public MappingMongoConverter(MongoDatabaseFactory mongoDbFactory, MappingContext, MongoPersistentProperty> mappingContext) { this(new DefaultDbRefResolver(mongoDbFactory), mappingContext); setCodecRegistryProvider(mongoDbFactory); @@ -1671,12 +1671,12 @@ public Class getWriteTarget(Class source) { } /** - * Create a new {@link MappingMongoConverter} using the given {@link MongoDbFactory} when loading {@link DBRef}. + * Create a new {@link MappingMongoConverter} using the given {@link MongoDatabaseFactory} when loading {@link DBRef}. * * @return new instance of {@link MappingMongoConverter}. Never {@literal null}. * @since 2.1.6 */ - public MappingMongoConverter with(MongoDbFactory dbFactory) { + public MappingMongoConverter with(MongoDatabaseFactory dbFactory) { MappingMongoConverter target = new MappingMongoConverter(new DefaultDbRefResolver(dbFactory), mappingContext); target.applicationContext = applicationContext; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java index ab4428b3f1..ec910a8680 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java @@ -26,7 +26,7 @@ import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.MappingContextEvent; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.UncategorizedMongoDbException; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder; import org.springframework.data.mongodb.core.mapping.Document; @@ -62,7 +62,7 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener> initCursor(MongoTemplate t } MongoDatabase db = StringUtils.hasText(options.getDatabaseName()) - ? template.getMongoDbFactory().getDb(options.getDatabaseName()) + ? template.getMongoDbFactory().getMongoDatabase(options.getDatabaseName()) : template.getDb(); ChangeStreamIterable iterable; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index 5153493a72..7a7b2d64d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -15,7 +15,7 @@ */ package org.springframework.data.mongodb.core.messaging; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -57,7 +57,7 @@ interface RequestOptions { * Get the database name of the db. * * @return the name of the database to subscribe to. Can be {@literal null} in which case the default - * {@link MongoDbFactory#getMongoDatabase() database} is used. + * {@link MongoDatabaseFactory#getMongoDatabase() database} is used. */ @Nullable default String getDatabaseName() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 3d7b639c2f..453a565610 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -26,7 +26,7 @@ import org.bson.Document; import org.bson.types.ObjectId; import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Query; import org.springframework.lang.Nullable; @@ -54,28 +54,28 @@ */ public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOperations, ResourcePatternResolver { - private final MongoDbFactory dbFactory; + private final MongoDatabaseFactory dbFactory; private final @Nullable String bucket; /** - * Creates a new {@link GridFsTemplate} using the given {@link MongoDbFactory} and {@link MongoConverter}. + * Creates a new {@link GridFsTemplate} using the given {@link MongoDatabaseFactory} and {@link MongoConverter}. * * @param dbFactory must not be {@literal null}. * @param converter must not be {@literal null}. */ - public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter) { + public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter) { this(dbFactory, converter, null); } /** - * Creates a new {@link GridFsTemplate} using the given {@link MongoDbFactory} and {@link MongoConverter}. + * Creates a new {@link GridFsTemplate} using the given {@link MongoDatabaseFactory} and {@link MongoConverter}. * * @param dbFactory must not be {@literal null}. * @param converter must not be {@literal null}. * @param bucket */ - public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter, @Nullable String bucket) { + public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter, @Nullable String bucket) { super(converter); diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd index 98deb2ac42..a6f5ceffd4 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd @@ -51,7 +51,7 @@ Defines a MongoDbFactory for connecting to a specific database +The name of the MongoDatabaseFactory definition (by default "mongoDbFactory").]]> @@ -91,7 +91,7 @@ See https://docs.mongodb.com/manual/reference/connection-string/ for full docume - The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + The WriteConcern that will be the default value used when asking the MongoDatabaseFactory for a DB object @@ -173,11 +173,11 @@ The base package in which to scan for entities annotated with @Document - The reference to a DbFactory. + The reference to a MongoDatabaseFactory. - + @@ -765,12 +765,12 @@ The reference to a MappingMongoConverter instance. use="optional"> - The reference to a DbFactory. + The reference to a MongoDatabaseFactory. + type="org.springframework.data.mongodb.MongoDatabaseFactory" /> @@ -778,7 +778,7 @@ The reference to a MappingMongoConverter instance. - The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + The WriteConcern that will be the default value used when asking the MongoDatabaseFactory for a DB object @@ -817,11 +817,11 @@ The reference to a MappingMongoConverter instance. - The reference to a DbFactory. + The reference to a MongoDatabaseFactory. - + diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java index a9a8ff183c..700b6f6a67 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java @@ -47,7 +47,7 @@ public class MongoDatabaseUtilsUnitTests { @Mock ClientSession session; @Mock ServerSession serverSession; - @Mock MongoDbFactory dbFactory; + @Mock MongoDatabaseFactory dbFactory; @Mock MongoDatabase db; @Mock UserTransaction userTransaction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java index fadb174520..e391866ae7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java @@ -47,8 +47,8 @@ public class MongoTransactionManagerUnitTests { @Mock ClientSession session; @Mock ClientSession session2; @Mock ServerSession serverSession; - @Mock MongoDbFactory dbFactory; - @Mock MongoDbFactory dbFactory2; + @Mock MongoDatabaseFactory dbFactory; + @Mock MongoDatabaseFactory dbFactory2; @Mock MongoDatabase db; @Mock MongoDatabase db2; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index b4ae2c2b4f..c811bba4b8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -31,7 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoTypeMapper; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; @@ -79,7 +79,7 @@ public void containsMongoDbFactoryButNoMongoBean() { AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); - assertThat(context.getBean(MongoDbFactory.class)).isNotNull(); + assertThat(context.getBean(MongoDatabaseFactory.class)).isNotNull(); assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> context.getBean(MongoClient.class)); context.close(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java index 013dd60d73..5754a26021 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests.java @@ -22,13 +22,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; /** - * Integration tests for {@link MongoDbFactory}. + * Integration tests for {@link MongoDatabaseFactory}. * * @author Thomas Risberg * @author Oliver Gierke diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 9736077eae..309d85ebc8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -28,8 +28,8 @@ import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.util.ReflectionTestUtils; @@ -58,7 +58,8 @@ public void setUp() { @Test // DATAMONGO-2199 public void testWriteConcern() throws Exception { - SimpleMongoClientDbFactory dbFactory = new SimpleMongoClientDbFactory(MongoTestUtils.client(), "database"); + SimpleMongoClientDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), + "database"); dbFactory.setWriteConcern(WriteConcern.ACKNOWLEDGED); dbFactory.getMongoDatabase(); @@ -85,7 +86,7 @@ public void readsReplicasWriteConcernCorrectly() { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext( "namespace/db-factory-bean-custom-write-concern.xml"); - MongoDbFactory factory = ctx.getBean("second", MongoDbFactory.class); + MongoDatabaseFactory factory = ctx.getBean("second", MongoDatabaseFactory.class); MongoDatabase db = factory.getMongoDatabase(); assertThat(db.getWriteConcern()).isEqualTo(WriteConcern.W2); @@ -120,7 +121,7 @@ public void setsUpMongoDbFactoryUsingAMongoUriWithoutCredentials() { ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); - MongoDbFactory dbFactory = factory.getBean("mongoDbFactory", MongoDbFactory.class); + MongoDatabaseFactory dbFactory = factory.getBean("mongoDbFactory", MongoDatabaseFactory.class); MongoDatabase db = dbFactory.getMongoDatabase(); assertThat(db.getName()).isEqualTo("database"); } @@ -166,8 +167,8 @@ public void usesConnectionStringToCreateClientClient() { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml"); - MongoDbFactory dbFactory = ctx.getBean("with-connection-string", MongoDbFactory.class); - assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + MongoDatabaseFactory dbFactory = ctx.getBean("with-connection-string", MongoDatabaseFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDatabaseFactory.class); assertThat(ReflectionTestUtils.getField(dbFactory, "mongoClient")) .isInstanceOf(com.mongodb.client.MongoClient.class); } @@ -177,15 +178,15 @@ public void usesMongoClientClientRef() { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml"); - MongoDbFactory dbFactory = ctx.getBean("with-mongo-client-client-ref", MongoDbFactory.class); - assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + MongoDatabaseFactory dbFactory = ctx.getBean("with-mongo-client-client-ref", MongoDatabaseFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDatabaseFactory.class); assertThat(ReflectionTestUtils.getField(dbFactory, "mongoClient")) .isInstanceOf(com.mongodb.client.MongoClient.class); } private static void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) { - SimpleMongoClientDbFactory dbFactory = ctx.getBean("first", SimpleMongoClientDbFactory.class); + SimpleMongoClientDatabaseFactory dbFactory = ctx.getBean("first", SimpleMongoClientDatabaseFactory.class); MongoDatabase db = dbFactory.getMongoDatabase(); assertThat(db.getName()).isEqualTo("db"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index e6139a6781..2824cd89a0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -24,7 +24,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoClientFactoryBean; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -117,7 +117,7 @@ public void testMongoSingletonWithSslEnabledAndCustomSslSocketFactory() throws E public void testSecondMongoDbFactory() { assertThat(ctx.containsBean("secondMongoDbFactory")).isTrue(); - MongoDbFactory dbf = (MongoDbFactory) ctx.getBean("secondMongoDbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) ctx.getBean("secondMongoDbFactory"); MongoClient mongo = (MongoClient) getField(dbf, "mongoClient"); assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); @@ -129,7 +129,7 @@ public void testThirdMongoDbFactory() { assertThat(ctx.containsBean("thirdMongoDbFactory")).isTrue(); - MongoDbFactory dbf = (MongoDbFactory) ctx.getBean("thirdMongoDbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) ctx.getBean("thirdMongoDbFactory"); MongoClient mongo = (MongoClient) getField(dbf, "mongoClient"); assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); @@ -142,7 +142,7 @@ public void testMongoTemplateFactory() { assertThat(ctx.containsBean("mongoTemplate")).isTrue(); MongoOperations operations = (MongoOperations) ctx.getBean("mongoTemplate"); - MongoDbFactory dbf = (MongoDbFactory) getField(operations, "mongoDbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "mongoDbFactory"); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); MongoConverter converter = (MongoConverter) getField(operations, "mongoConverter"); @@ -155,7 +155,7 @@ public void testSecondMongoTemplateFactory() { assertThat(ctx.containsBean("anotherMongoTemplate")).isTrue(); MongoOperations operations = (MongoOperations) ctx.getBean("anotherMongoTemplate"); - MongoDbFactory dbf = (MongoDbFactory) getField(operations, "mongoDbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "mongoDbFactory"); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); WriteConcern writeConcern = (WriteConcern) getField(operations, "writeConcern"); @@ -168,7 +168,7 @@ public void testGridFsTemplateFactory() { assertThat(ctx.containsBean("gridFsTemplate")).isTrue(); GridFsOperations operations = (GridFsOperations) ctx.getBean("gridFsTemplate"); - MongoDbFactory dbf = (MongoDbFactory) getField(operations, "dbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "dbFactory"); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); MongoConverter converter = (MongoConverter) getField(operations, "converter"); @@ -181,7 +181,7 @@ public void testSecondGridFsTemplateFactory() { assertThat(ctx.containsBean("secondGridFsTemplate")).isTrue(); GridFsOperations operations = (GridFsOperations) ctx.getBean("secondGridFsTemplate"); - MongoDbFactory dbf = (MongoDbFactory) getField(operations, "dbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "dbFactory"); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); assertThat(getField(operations, "bucket")).isEqualTo(null); @@ -195,7 +195,7 @@ public void testThirdGridFsTemplateFactory() { assertThat(ctx.containsBean("thirdGridFsTemplate")).isTrue(); GridFsOperations operations = (GridFsOperations) ctx.getBean("thirdGridFsTemplate"); - MongoDbFactory dbf = (MongoDbFactory) getField(operations, "dbFactory"); + MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "dbFactory"); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); assertThat(getField(operations, "bucket")).isEqualTo("bucketString"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java index 48b668b6ba..58b8e368f4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.springframework.data.geo.Point; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -45,7 +45,7 @@ public class CountQueryUnitTests { MongoMappingContext context; MappingMongoConverter converter; - MongoDbFactory factory = mock(MongoDbFactory.class); + MongoDatabaseFactory factory = mock(MongoDatabaseFactory.class); @Before public void setUp() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index d35056d096..8034447cc5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -43,7 +43,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.annotation.Id; import org.springframework.data.mapping.callback.EntityCallbacks; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -89,7 +89,7 @@ public class DefaultBulkOperationsUnitTests { MongoTemplate template; @Mock MongoDatabase database; @Mock(answer = Answers.RETURNS_DEEP_STUBS) MongoCollection collection; - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @Mock DbRefResolver dbRefResolver; @Captor ArgumentCaptor>> captor; MongoConverter converter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java index 1a7b11ef28..7d7c8ff8f1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java @@ -28,7 +28,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.index.HashedIndex; @@ -51,7 +51,7 @@ public class DefaultIndexOperationsUnitTests { MongoTemplate template; - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @Mock MongoDatabase db; @Mock MongoCollection collection; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java index 57685872e4..24d9862ee0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java @@ -67,7 +67,7 @@ public class ExecutableFindOperationSupportTests { public void setUp() { template = new MongoTemplate( - new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableFindOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableFindOperationSupportTests")); template.dropCollection(STAR_WARS); template.dropCollection(STAR_WARS_PLANETS); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java index a638730ba6..7268bc4ba6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java @@ -49,7 +49,7 @@ public class ExecutableRemoveOperationSupportTests { public void setUp() { template = new MongoTemplate( - new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableRemoveOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableRemoveOperationSupportTests")); template.dropCollection(STAR_WARS); han = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java index 878eb56ee0..ac897108a9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java @@ -52,7 +52,7 @@ public class ExecutableUpdateOperationSupportTests { public void setUp() { template = new MongoTemplate( - new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); template.dropCollection(STAR_WARS); han = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 44dee0ad71..4ec1a1bdcb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -65,7 +65,7 @@ import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.LazyLoadingProxy; @@ -132,7 +132,7 @@ public class MongoTemplateTests { @Autowired MongoTemplate template; - @Autowired MongoDbFactory factory; + @Autowired MongoDatabaseFactory factory; ConfigurableApplicationContext context; MongoTemplate mappingTemplate; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index 8f1cd6e0a1..b78a736b9a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -37,7 +37,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Persistable; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.test.util.AfterTransactionAssertion; @@ -91,7 +91,7 @@ protected boolean autoIndexCreation() { } @Bean - MongoTransactionManager txManager(MongoDbFactory dbFactory) { + MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 7b6d1dfc95..b6a4ac6b44 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -61,7 +61,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.geo.Point; import org.springframework.data.mapping.callback.EntityCallbacks; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; @@ -133,7 +133,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { MongoTemplate template; - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @Mock MongoClient mongo; @Mock MongoDatabase db; @Mock MongoCollection collection; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index a98385dc40..d519b9d892 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -59,7 +59,7 @@ class MongoTemplateUpdateTests { void setUp() { client = MongoTestUtils.client(); - template = new MongoTemplate(new SimpleMongoClientDbFactory(client, DB_NAME)); + template = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, DB_NAME)); MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Score.class), client); MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Versioned.class), client); 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 59ddf9f26b..e10be32546 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 @@ -27,7 +27,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; @@ -45,7 +45,7 @@ @RunWith(MockitoJUnitRunner.class) public class QueryCursorPreparerUnitTests { - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @Mock MongoExceptionTranslator exceptionTranslatorMock; @Mock FindIterable cursor; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java index 39e4a3b774..af98e55d75 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java @@ -50,8 +50,6 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import com.mongodb.reactivestreams.client.MongoClients; - /** * Integration tests for {@link ReactiveFindOperationSupport}. * @@ -71,7 +69,7 @@ public class ReactiveFindOperationSupportTests { public void setUp() { blocking = new MongoTemplate( - new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableFindOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableFindOperationSupportTests")); recreateCollection(STAR_WARS, false); insertObjects(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java index f78c3bd78f..0be743d9d2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java @@ -28,8 +28,6 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import com.mongodb.reactivestreams.client.MongoClients; - /** * Integration tests for {@link ReactiveRemoveOperationSupport}. * @@ -48,7 +46,7 @@ public class ReactiveRemoveOperationSupportTests { public void setUp() { blocking = new MongoTemplate( - new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableRemoveOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableRemoveOperationSupportTests")); blocking.dropCollection(STAR_WARS); han = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java index 1c721753a2..756d1c288c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java @@ -49,7 +49,7 @@ public class ReactiveUpdateOperationSupportTests { public void setUp() { blocking = new MongoTemplate( - new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); blocking.dropCollection(STAR_WARS); han = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java index 22acab58ae..c808d7f300 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java @@ -39,7 +39,6 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Test; import org.junit.rules.TestRule; import org.mockito.Mockito; @@ -50,7 +49,7 @@ import org.springframework.data.geo.Point; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.LazyLoadingException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.SessionAwareMethodInterceptor; import org.springframework.data.mongodb.core.MongoTemplate.SessionBoundMongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; @@ -97,7 +96,7 @@ public void setUp() { client = MongoTestUtils.replSetClient(); - MongoDbFactory factory = new SimpleMongoClientDbFactory(client, "session-bound-mongo-template-tests") { + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, "session-bound-mongo-template-tests") { @Override public MongoDatabase getMongoDatabase() throws DataAccessException { @@ -393,7 +392,7 @@ MongoDatabase command(int index) { return spiedDatabases.get(index); } - private MongoConverter getDefaultMongoConverter(MongoDbFactory factory) { + private MongoConverter getDefaultMongoConverter(MongoDatabaseFactory factory) { DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); MongoCustomConversions conversions = new MongoCustomConversions(Collections.emptyList()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java index eee395f824..482aea84e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java @@ -33,7 +33,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.MongoTemplate.SessionBoundMongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; @@ -78,7 +78,7 @@ public class SessionBoundMongoTemplateUnitTests { SessionBoundMongoTemplate template; - MongoDbFactory factory; + MongoDatabaseFactory factory; @Mock(answer = Answers.RETURNS_DEEP_STUBS) MongoCollection collection; @Mock MongoDatabase database; @@ -123,7 +123,7 @@ public void setUp() { when(cursor.hasNext()).thenReturn(false); when(findIterable.projection(any())).thenReturn(findIterable); - factory = new SimpleMongoClientDbFactory(client, "foo"); + factory = new SimpleMongoClientDatabaseFactory(client, "foo"); this.mappingContext = new MongoMappingContext(); this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java similarity index 79% rename from spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java index 7369c82727..89da5de00f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java @@ -27,7 +27,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.aop.framework.AopProxyUtils; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.ConnectionString; @@ -36,14 +36,14 @@ import com.mongodb.client.MongoDatabase; /** - * Unit tests for {@link SimpleMongoClientDbFactory}. + * Unit tests for {@link SimpleMongoClientDatabaseFactory}. * * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) -public class SimpleMongoClientDbFactoryUnitTests { +public class SimpleMongoClientDatabaseFactoryUnitTests { @Mock MongoClient mongo; @Mock ClientSession clientSession; @@ -63,9 +63,9 @@ public void rejectsIllegalDatabaseNames() { @Test // DATADOC-254 @SuppressWarnings("deprecation") public void allowsDatabaseNames() { - new SimpleMongoClientDbFactory(mongo, "foo-bar"); - new SimpleMongoClientDbFactory(mongo, "foo_bar"); - new SimpleMongoClientDbFactory(mongo, "foo01231bar"); + new SimpleMongoClientDatabaseFactory(mongo, "foo-bar"); + new SimpleMongoClientDatabaseFactory(mongo, "foo_bar"); + new SimpleMongoClientDatabaseFactory(mongo, "foo01231bar"); } @Test // DATADOC-295 @@ -74,7 +74,7 @@ public void mongoUriConstructor() { ConnectionString mongoURI = new ConnectionString( "mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); - MongoDbFactory mongoDbFactory = new SimpleMongoClientDbFactory(mongoURI); + MongoDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(mongoURI); assertThat(getField(mongoDbFactory, "databaseName").toString()).isEqualTo("myDatabase"); } @@ -84,7 +84,7 @@ public void constructsMongoClientAccordingToMongoUri() { ConnectionString uri = new ConnectionString( "mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); - SimpleMongoClientDbFactory factory = new SimpleMongoClientDbFactory(uri); + SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(uri); assertThat(getField(factory, "databaseName").toString()).isEqualTo("myDataBase"); } @@ -94,8 +94,8 @@ public void cascadedWithSessionUsesRootFactory() { when(mongo.getDatabase("foo")).thenReturn(database); - MongoDbFactory factory = new SimpleMongoClientDbFactory(mongo, "foo"); - MongoDbFactory wrapped = factory.withSession(clientSession).withSession(clientSession); + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(mongo, "foo"); + MongoDatabaseFactory wrapped = factory.withSession(clientSession).withSession(clientSession); InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase()); @@ -106,7 +106,7 @@ public void cascadedWithSessionUsesRootFactory() { } private void rejectsDatabaseName(String databaseName) { - assertThatThrownBy(() -> new SimpleMongoClientDbFactory(mongo, databaseName)) + assertThatThrownBy(() -> new SimpleMongoClientDatabaseFactory(mongo, databaseName)) .isInstanceOf(IllegalArgumentException.class); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java index f054296dc4..4285a592bb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java @@ -27,7 +27,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -40,7 +40,7 @@ @RunWith(MockitoJUnitRunner.class) public class FilterExpressionUnitTests { - @Mock MongoDbFactory mongoDbFactory; + @Mock MongoDatabaseFactory mongoDbFactory; private AggregationOperationContext aggregationContext; private MongoMappingContext mappingContext; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java index 388ec02bdf..c4b2500e1f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java @@ -23,7 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mapping.context.InvalidPersistentPropertyPath; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -41,7 +41,7 @@ @ContextConfiguration("classpath:infrastructure.xml") public class SpelExpressionTransformerIntegrationTests { - @Autowired MongoDbFactory mongoDbFactory; + @Autowired MongoDatabaseFactory mongoDbFactory; SpelExpressionTransformer transformer; DbRefResolver dbRefResolver; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java index f37bd3f8b4..c7657bd1b1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java @@ -31,7 +31,7 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.convert.CustomConversions; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; /** @@ -46,7 +46,7 @@ public class CustomConvertersUnitTests { @Mock BarToDocumentConverter barToDocumentConverter; @Mock DocumentToBarConverter documentToBarConverter; - @Mock MongoDbFactory mongoDbFactory; + @Mock MongoDatabaseFactory mongoDbFactory; MongoMappingContext context; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index 4bb8d0a30f..41c7ec1c7f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -47,7 +47,7 @@ import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PropertyPath; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.convert.MappingMongoConverterUnitTests.Person; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -75,7 +75,7 @@ public class DbRefMappingMongoConverterUnitTests { MappingMongoConverter converter; MongoMappingContext mappingContext; - @Mock MongoDbFactory dbFactory; + @Mock MongoDatabaseFactory dbFactory; DefaultDbRefResolver dbRefResolver; @Before diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index 9033f5c5c6..639ca4afc2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -33,7 +33,7 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; import com.mongodb.DBRef; @@ -50,7 +50,7 @@ @RunWith(MockitoJUnitRunner.class) public class DefaultDbRefResolverUnitTests { - @Mock MongoDbFactory factoryMock; + @Mock MongoDatabaseFactory factoryMock; @Mock MongoDatabase dbMock; @Mock MongoCollection collectionMock; @Mock FindIterable cursorMock; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index 49cb8ef163..31dd079cc9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -31,14 +31,13 @@ import org.junit.Before; import org.junit.Test; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.test.util.MongoTestUtils; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; /** * Integration tests for {@link MappingMongoConverter}. @@ -59,7 +58,7 @@ public void setUp() { client = MongoTestUtils.client(); client.getDatabase("mapping-converter-tests").drop(); - MongoDbFactory factory = new SimpleMongoClientDbFactory(client, "mapping-converter-tests"); + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, "mapping-converter-tests"); dbRefResolver = spy(new DefaultDbRefResolver(factory)); mappingContext = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java index 9dc7f0b943..30ab0ab093 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java @@ -38,7 +38,7 @@ import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.domain.ExampleMatcher.*; import org.springframework.data.geo.Point; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.QueryMapperUnitTests.ClassWithGeoTypes; import org.springframework.data.mongodb.core.convert.QueryMapperUnitTests.WithDBRef; import org.springframework.data.mongodb.core.mapping.DBRef; @@ -59,7 +59,7 @@ public class MongoExampleMapperUnitTests { MongoMappingContext context; MappingMongoConverter converter; - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @Before public void setUp() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index daf6bd064c..9f00affefd 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -42,7 +42,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.geo.Point; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; @@ -60,7 +60,6 @@ import org.springframework.data.mongodb.core.query.Query; import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; /** * Unit tests for {@link QueryMapper}. @@ -78,7 +77,7 @@ public class QueryMapperUnitTests { MongoMappingContext context; MappingMongoConverter converter; - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @BeforeEach void beforeEach() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index 2cc6c1542c..01eddc0268 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -46,7 +46,7 @@ import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; import org.springframework.data.mapping.MappingException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -69,7 +69,7 @@ @RunWith(MockitoJUnitRunner.class) public class UpdateMapperUnitTests { - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; MappingMongoConverter converter; MongoMappingContext context; UpdateMapper mapper; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 7f40c174a4..3688aef58d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -36,7 +36,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoCollectionUtils; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; @@ -65,7 +65,7 @@ public class IndexingIntegrationTests { @Autowired MongoOperations operations; - @Autowired MongoDbFactory mongoDbFactory; + @Autowired MongoDatabaseFactory mongoDbFactory; @Autowired ConfigurableApplicationContext context; @Configuration diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index def6e4ee1d..78d614d6e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -31,7 +31,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.data.geo.Point; import org.springframework.data.mapping.context.MappingContextEvent; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.Document; @@ -58,7 +58,7 @@ @RunWith(MockitoJUnitRunner.class) public class MongoPersistentEntityIndexCreatorUnitTests { - private @Mock MongoDbFactory factory; + private @Mock MongoDatabaseFactory factory; private @Mock MongoDatabase db; private @Mock MongoCollection collection; private MongoTemplate mongoTemplate; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java index 7f0c11b299..7e3f07d4c1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java @@ -76,7 +76,7 @@ protected void cleanDb() { template.dropCollection("jmr1_out"); template.dropCollection("jmr1"); template.dropCollection("jmrWithGeo"); - template.getMongoDbFactory().getDb("jmr1-out-db").drop(); + template.getMongoDbFactory().getMongoDatabase("jmr1-out-db").drop(); } @Test // DATADOC-7 @@ -167,8 +167,9 @@ public void mapReduceWithOutputDatabaseShouldWorkCorrectly() { mongoTemplate.mapReduce("jmr1", MAP_FUNCTION, REDUCE_FUNCTION, options().outputDatabase("jmr1-out-db").outputCollection("jmr1-out"), ValueObject.class); - assertThat(template.getMongoDbFactory().getDb("jmr1-out-db").listCollectionNames().into(new ArrayList<>())) - .contains("jmr1-out"); + assertThat( + template.getMongoDbFactory().getMongoDatabase("jmr1-out-db").listCollectionNames().into(new ArrayList<>())) + .contains("jmr1-out"); } @Test // DATADOC-7 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index 770055049b..66323d31c9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -33,9 +33,9 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoServerCondition; @@ -60,7 +60,7 @@ public class DefaultMessageListenerContainerTests { public static final Duration TIMEOUT = Duration.ofSeconds(2); - MongoDbFactory dbFactory; + MongoDatabaseFactory dbFactory; MongoCollection collection; MongoCollection collection2; @@ -70,7 +70,7 @@ public class DefaultMessageListenerContainerTests { @BeforeEach void beforeEach() { - dbFactory = new SimpleMongoClientDbFactory(MongoTestUtils.client(), DATABASE_NAME); + dbFactory = new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), DATABASE_NAME); template = new MongoTemplate(dbFactory); template.dropCollection(COLLECTION_NAME); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 2944aff945..f3c99999f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -41,7 +41,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -69,7 +69,7 @@ public class GridFsTemplateIntegrationTests { Resource resource = new ClassPathResource("gridfs/gridfs.xml"); @Autowired GridFsOperations operations; - @Autowired SimpleMongoClientDbFactory mongoClient; + @Autowired SimpleMongoClientDatabaseFactory mongoClient; @Before public void setUp() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 6656a6cada..a444b99b52 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -45,7 +45,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; @@ -72,7 +72,7 @@ public class ReactiveGridFsTemplateTests { Resource resource = new ClassPathResource("gridfs/gridfs.xml"); @Autowired ReactiveGridFsOperations operations; - @Autowired SimpleMongoClientDbFactory mongoClient; + @Autowired SimpleMongoClientDatabaseFactory mongoClient; @Autowired ReactiveMongoDatabaseFactory dbFactory; @Autowired MongoConverter mongoConverter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java index 9f038f8f10..2143cbc5fb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java @@ -30,7 +30,7 @@ import org.springframework.core.Constants; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -78,14 +78,14 @@ public void setUp() throws Exception { this.mongo = MongoClients.create(); - SimpleMongoClientDbFactory mongoDbFactory = new SimpleMongoClientDbFactory(this.mongo, DATABASE_NAME); + SimpleMongoClientDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(this.mongo, DATABASE_NAME); MongoMappingContext context = new MongoMappingContext(); context.setInitialEntitySet(Collections.singleton(Person.class)); context.afterPropertiesSet(); this.converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context); - this.operations = new MongoTemplate(new SimpleMongoClientDbFactory(this.mongo, DATABASE_NAME), converter); + this.operations = new MongoTemplate(new SimpleMongoClientDatabaseFactory(this.mongo, DATABASE_NAME), converter); MongoRepositoryFactoryBean factory = new MongoRepositoryFactoryBean( PersonRepository.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java index 5b5556e11f..247f958c89 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java @@ -133,12 +133,11 @@ public void composedAnnotationFindQueryShouldWorkWhenUsingComplexId() { } @Test // DATAMONGO-1373 - @MongoVersion(until = "4.0.999") public void composedAnnotationFindMetaShouldWorkWhenUsingComplexId() { repo.save(userWithId); - assertThat(repo.findUsersUsingComposedMetaAnnotationByUserIds(Arrays.asList(id))).hasSize(0); + assertThat(repo.findUsersUsingComposedMetaAnnotationByUserIds(Arrays.asList(id))).hasSize(1); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index 58b2162689..5969d2b7f2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -33,7 +33,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.Persistable; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.MongoTemplate; @@ -86,7 +86,7 @@ protected String getDatabaseName() { } @Bean - MongoTransactionManager txManager(MongoDbFactory dbFactory) { + MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java index 88d2b240b3..874ef840f1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java @@ -18,10 +18,10 @@ import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.test.util.MongoTestUtils; /** @@ -35,7 +35,7 @@ class MongoTemplateProducer { @ApplicationScoped public MongoOperations createMongoTemplate() { - MongoDbFactory factory = new SimpleMongoClientDbFactory(MongoTestUtils.client(), "database"); + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "database"); return new MongoTemplate(factory); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java index 64fe346243..5bc6f3b540 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java @@ -23,7 +23,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.repository.PersonRepository; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; @@ -44,7 +44,7 @@ static class Config { @Bean public MongoOperations mongoTemplate() throws Exception { - return new MongoTemplate(new SimpleMongoClientDbFactory(MongoTestUtils.client(), "database")); + return new MongoTemplate(new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "database")); } } 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 4d5cf58f07..87e87d880c 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 @@ -41,7 +41,7 @@ import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; import org.springframework.data.mongodb.core.MongoOperations; @@ -91,7 +91,7 @@ public void setUp() { doReturn(persitentEntityMock).when(mappingContextMock).getRequiredPersistentEntity(Mockito.any(Class.class)); doReturn(Person.class).when(persitentEntityMock).getType(); - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDbFactory.class)); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDatabaseFactory.class)); MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContextMock); converter.afterPropertiesSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java index ba4fbd8274..0e211ac5cb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java @@ -27,7 +27,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -48,7 +48,7 @@ @RunWith(MockitoJUnitRunner.class) public class ConvertingParameterAccessorUnitTests { - @Mock MongoDbFactory factory; + @Mock MongoDatabaseFactory factory; @Mock MongoParameterAccessor accessor; MongoMappingContext context; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index b40e1b3913..a25106fce1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -37,7 +37,7 @@ import org.springframework.data.geo.Polygon; import org.springframework.data.geo.Shape; import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.Venue; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -77,7 +77,7 @@ public void beforeEach() { context = new MongoMappingContext(); - DbRefResolver resolver = new DefaultDbRefResolver(mock(MongoDbFactory.class)); + DbRefResolver resolver = new DefaultDbRefResolver(mock(MongoDatabaseFactory.class)); converter = new MappingMongoConverter(resolver, context); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java index 2b9ce86991..4349f76004 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java @@ -31,7 +31,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -70,7 +70,7 @@ public class PartTreeMongoQueryUnitTests { public void setUp() { mappingContext = new MongoMappingContext(); - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDbFactory.class)); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDatabaseFactory.class)); MongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext); doReturn(converter).when(mongoOperationsMock).getConverter(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java index 2f8cc5d8f6..17e7e0fb7c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java @@ -29,7 +29,7 @@ import org.springframework.dao.PermissionDeniedDataAccessException; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.Address; @@ -58,7 +58,7 @@ public class QuerydslMongoPredicateExecutorIntegrationTests { @Autowired MongoOperations operations; - @Autowired MongoDbFactory dbFactory; + @Autowired MongoDatabaseFactory dbFactory; QuerydslMongoPredicateExecutor repository; diff --git a/spring-data-mongodb/src/test/resources/geospatial.xml b/spring-data-mongodb/src/test/resources/geospatial.xml index a28863cefe..340be93c6d 100644 --- a/spring-data-mongodb/src/test/resources/geospatial.xml +++ b/spring-data-mongodb/src/test/resources/geospatial.xml @@ -5,20 +5,20 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd"> - - - + + + - + - + - + diff --git a/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml b/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml index d6aeec9d55..bcba3dfb38 100644 --- a/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml +++ b/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml @@ -32,7 +32,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/infrastructure.xml b/spring-data-mongodb/src/test/resources/infrastructure.xml index 5a80d0aca7..7bdb2708d1 100644 --- a/spring-data-mongodb/src/test/resources/infrastructure.xml +++ b/spring-data-mongodb/src/test/resources/infrastructure.xml @@ -8,7 +8,7 @@ - + diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index 0939983794..4006d1d3ae 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -7,7 +7,7 @@ Some of the changes affect the initial setup configuration as well as compile/ru == Dependency Changes -Instead of the single artifact uber jar `mongo-java-driver`, imports are now split to include separate artifacts: +Instead of the single artifact uber-jar `mongo-java-driver`, imports are now split to include separate artifacts: * `org.mongodb:mongodb-driver-core` (required) * `org.mongodb:mongodb-driver-sync` (optional) @@ -121,3 +121,22 @@ Element | Comment | Namespace element for `com.mongodb.MongoClientSettings`. |=== + +.Deprecations: +|=== +2.x | Replacement in 3.x | Comment + +| `MongoDbFactorySupport` +| `MongoDatabaseFactorySupport` +| + +| `SimpleMongoClientDbFactory` +| `SimpleMongoClientDatabaseFactory` +| + +| `MongoDbFactory` +| `MongoDatabaseFactory` +| + +|=== + From 6049541d0aa2936339da1aeab005a8cef8f35227 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 13 Dec 2019 09:40:38 +0100 Subject: [PATCH 0046/1381] DATAMONGO-2427 - Polishing. Replace leftovers to Mongo 2.x API with Document and MongoDatabase references and tweak Javadoc. Reorder field declarations to class header. Reflect 3.0 versions in schema configuration. Add TODO markers to disabled tests. Reflect changes in documentation. Enable disabled test. Original pull request: #823. --- .../mongodb/core/MongoClientFactoryBean.java | 18 +-- .../core/MongoClientSettingsFactoryBean.java | 133 ++++++++++-------- .../data/mongodb/core/MongoTemplate.java | 3 +- ...eactiveMongoClientSettingsFactoryBean.java | 1 + .../core/aggregation/AggregationOptions.java | 4 +- .../core/index/PartialIndexFilter.java | 4 +- .../core/mapreduce/MapReduceOptions.java | 2 +- .../main/resources/META-INF/spring.schemas | 3 +- .../config/MongoClientNamespaceTests.java | 1 - .../mongodb/config/MongoNamespaceTests.java | 18 +-- .../core/MongoClientFactoryBeanUnitTests.java | 24 +--- ...ngoClientSettingsFactoryBeanUnitTests.java | 2 +- .../core/QueryCursorPreparerUnitTests.java | 2 + ...leMongoClientDatabaseFactoryUnitTests.java | 8 +- src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/preface.adoc | 11 +- .../client-session-transactions.adoc | 6 +- src/main/asciidoc/reference/mapping.adoc | 8 +- src/main/asciidoc/reference/migrating.adoc | 5 +- src/main/asciidoc/reference/mongo-3.adoc | 11 +- .../reference/mongo-repositories.adoc | 4 +- src/main/asciidoc/reference/mongodb.adoc | 38 +++-- src/main/asciidoc/upgrading.adoc | 2 +- 23 files changed, 144 insertions(+), 165 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index e103fd37fb..d4ec1f5d82 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -144,10 +144,12 @@ protected MongoClient createInstance() throws Exception { } /** - * Create {@link MongoClientSettings} based on configuration and priority (lower is better).
      - * 1. {@link MongoClientFactoryBean#mongoClientSettings}
      - * 2. {@link MongoClientFactoryBean#connectionString}
      - * 3. default {@link MongoClientSettings} + * Create {@link MongoClientSettings} based on configuration and priority (lower is better). + *

        + *
      1. {@link MongoClientFactoryBean#mongoClientSettings}
      2. + *
      3. {@link MongoClientFactoryBean#connectionString}
      4. + *
      5. default {@link MongoClientSettings}
      6. + *
      * * @since 3.0 */ @@ -220,7 +222,7 @@ protected MongoClientSettings computeClientSetting() { }) // .applyToConnectionPoolSettings(settings -> { - applySettings(it -> settings.maintenanceFrequency(it.longValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.maintenanceFrequency(it, TimeUnit.MILLISECONDS), computeSettingsValue((ConnectionPoolSettings it) -> it.getMaintenanceFrequency(TimeUnit.MILLISECONDS), defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); @@ -239,7 +241,7 @@ protected MongoClientSettings computeClientSetting() { defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, connectionString.getMaxWaitTime())); - applySettings(it -> settings.maintenanceInitialDelay(it.longValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.maintenanceInitialDelay(it, TimeUnit.MILLISECONDS), computeSettingsValue( (ConnectionPoolSettings it) -> it.getMaintenanceInitialDelay(TimeUnit.MILLISECONDS), defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); @@ -253,11 +255,11 @@ protected MongoClientSettings computeClientSetting() { }) // .applyToSocketSettings(settings -> { - applySettings(it -> settings.connectTimeout(it.intValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.connectTimeout(it, TimeUnit.MILLISECONDS), computeSettingsValue((SocketSettings it) -> it.getConnectTimeout(TimeUnit.MILLISECONDS), defaultSettings.getSocketSettings(), socketSettings, connectionString.getConnectTimeout())); - applySettings(it -> settings.readTimeout(it.intValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.readTimeout(it, TimeUnit.MILLISECONDS), computeSettingsValue((SocketSettings it) -> it.getReadTimeout(TimeUnit.MILLISECONDS), defaultSettings.getSocketSettings(), socketSettings, connectionString.getSocketTimeout())); applySettings(settings::receiveBufferSize, computeSettingsValue(SocketSettings::getReceiveBufferSize, diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java index e688433b68..f8cf254cb3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java @@ -24,10 +24,10 @@ import javax.net.ssl.SSLContext; import org.bson.codecs.configuration.CodecRegistry; + import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; -import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import com.mongodb.AutoEncryptionSettings; @@ -45,6 +45,7 @@ * A factory bean for construction of a {@link MongoClientSettings} instance to be used with a MongoDB driver. * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean { @@ -65,18 +66,57 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean Socket Settings - private Integer socketConnectTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() + private int socketConnectTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() .getConnectTimeout(TimeUnit.MILLISECONDS); - private Integer socketReadTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() - .getReadTimeout(TimeUnit.MILLISECONDS); - private Integer socketReceiveBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReceiveBufferSize(); - private Integer socketSendBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getSendBufferSize(); + private int socketReadTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS); + private int socketReceiveBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReceiveBufferSize(); + private int socketSendBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getSendBufferSize(); + + // --> Cluster Settings + + private @Nullable String clusterSrvHost = DEFAULT_MONGO_SETTINGS.getClusterSettings().getSrvHost(); + private List clusterHosts = Collections.emptyList(); + private @Nullable ClusterConnectionMode clusterConnectionMode = null; + private ClusterType custerRequiredClusterType = DEFAULT_MONGO_SETTINGS.getClusterSettings().getRequiredClusterType(); + private String clusterRequiredReplicaSetName = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getRequiredReplicaSetName(); + private long clusterLocalThresholdMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getLocalThreshold(TimeUnit.MILLISECONDS); + private long clusterServerSelectionTimeoutMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getServerSelectionTimeout(TimeUnit.MILLISECONDS); + + // --> ConnectionPoolSettings + + private int poolMaxSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMaxSize(); + private int poolMinSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMinSize(); + private long poolMaxWaitTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxWaitTime(TimeUnit.MILLISECONDS); + private long poolMaxConnectionLifeTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxConnectionLifeTime(TimeUnit.MILLISECONDS); + private long poolMaxConnectionIdleTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxConnectionIdleTime(TimeUnit.MILLISECONDS); + private long poolMaintenanceInitialDelayMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaintenanceInitialDelay(TimeUnit.MILLISECONDS); + private long poolMaintenanceFrequencyMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaintenanceFrequency(TimeUnit.MILLISECONDS); + + // --> SSL Settings + + private boolean sslEnabled = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled(); + private boolean sslInvalidHostNameAllowed = DEFAULT_MONGO_SETTINGS.getSslSettings().isInvalidHostNameAllowed(); + private String sslProvider = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled() + ? DEFAULT_MONGO_SETTINGS.getSslSettings().getContext().getProvider().getName() + : ""; + + // encryption and retry + + private @Nullable AutoEncryptionSettings autoEncryptionSettings; /** * @param socketConnectTimeoutMS in msec * @see com.mongodb.connection.SocketSettings.Builder#connectTimeout(int, TimeUnit) */ - public void setSocketConnectTimeoutMS(Integer socketConnectTimeoutMS) { + public void setSocketConnectTimeoutMS(int socketConnectTimeoutMS) { this.socketConnectTimeoutMS = socketConnectTimeoutMS; } @@ -84,7 +124,7 @@ public void setSocketConnectTimeoutMS(Integer socketConnectTimeoutMS) { * @param socketReadTimeoutMS in msec * @see com.mongodb.connection.SocketSettings.Builder#readTimeout(int, TimeUnit) */ - public void setSocketReadTimeoutMS(Integer socketReadTimeoutMS) { + public void setSocketReadTimeoutMS(int socketReadTimeoutMS) { this.socketReadTimeoutMS = socketReadTimeoutMS; } @@ -92,7 +132,7 @@ public void setSocketReadTimeoutMS(Integer socketReadTimeoutMS) { * @param socketReceiveBufferSize * @see com.mongodb.connection.SocketSettings.Builder#receiveBufferSize(int) */ - public void setSocketReceiveBufferSize(Integer socketReceiveBufferSize) { + public void setSocketReceiveBufferSize(int socketReceiveBufferSize) { this.socketReceiveBufferSize = socketReceiveBufferSize; } @@ -100,22 +140,22 @@ public void setSocketReceiveBufferSize(Integer socketReceiveBufferSize) { * @param socketSendBufferSize * @see com.mongodb.connection.SocketSettings.Builder#sendBufferSize(int) */ - public void setSocketSendBufferSize(Integer socketSendBufferSize) { + public void setSocketSendBufferSize(int socketSendBufferSize) { this.socketSendBufferSize = socketSendBufferSize; } // --> Server Settings - private Long serverHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + private long serverHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() .getHeartbeatFrequency(TimeUnit.MILLISECONDS); - private Long serverMinHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + private long serverMinHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() .getMinHeartbeatFrequency(TimeUnit.MILLISECONDS); /** * @param serverHeartbeatFrequencyMS in msec * @see com.mongodb.connection.ServerSettings.Builder#heartbeatFrequency(long, TimeUnit) */ - public void setServerHeartbeatFrequencyMS(Long serverHeartbeatFrequencyMS) { + public void setServerHeartbeatFrequencyMS(long serverHeartbeatFrequencyMS) { this.serverHeartbeatFrequencyMS = serverHeartbeatFrequencyMS; } @@ -123,23 +163,12 @@ public void setServerHeartbeatFrequencyMS(Long serverHeartbeatFrequencyMS) { * @param serverMinHeartbeatFrequencyMS in msec * @see com.mongodb.connection.ServerSettings.Builder#minHeartbeatFrequency(long, TimeUnit) */ - public void setServerMinHeartbeatFrequencyMS(Long serverMinHeartbeatFrequencyMS) { + public void setServerMinHeartbeatFrequencyMS(long serverMinHeartbeatFrequencyMS) { this.serverMinHeartbeatFrequencyMS = serverMinHeartbeatFrequencyMS; } // --> Cluster Settings - private @Nullable String clusterSrvHost = DEFAULT_MONGO_SETTINGS.getClusterSettings().getSrvHost(); - private List clusterHosts = Collections.emptyList(); - private @Nullable ClusterConnectionMode clusterConnectionMode = null; - private ClusterType custerRequiredClusterType = DEFAULT_MONGO_SETTINGS.getClusterSettings().getRequiredClusterType(); - private String clusterRequiredReplicaSetName = DEFAULT_MONGO_SETTINGS.getClusterSettings() - .getRequiredReplicaSetName(); - private long clusterLocalThresholdMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() - .getLocalThreshold(TimeUnit.MILLISECONDS); - private long clusterServerSelectionTimeoutMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() - .getServerSelectionTimeout(TimeUnit.MILLISECONDS); - /** * @param clusterSrvHost * @see com.mongodb.connection.ClusterSettings.Builder#srvHost(String) @@ -158,7 +187,7 @@ public void setClusterHosts(ServerAddress[] clusterHosts) { /** * ???? - * + * * @param clusterConnectionMode * @see com.mongodb.connection.ClusterSettings.Builder#mode(ClusterConnectionMode) */ @@ -200,24 +229,11 @@ public void setClusterServerSelectionTimeoutMS(long clusterServerSelectionTimeou // --> ConnectionPoolSettings - private Integer poolMaxSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMaxSize(); - private Integer poolMinSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMinSize(); - private Long poolMaxWaitTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() - .getMaxWaitTime(TimeUnit.MILLISECONDS); - private Long poolMaxConnectionLifeTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() - .getMaxConnectionLifeTime(TimeUnit.MILLISECONDS); - private Long poolMaxConnectionIdleTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() - .getMaxConnectionIdleTime(TimeUnit.MILLISECONDS); - private Long poolMaintenanceInitialDelayMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() - .getMaintenanceInitialDelay(TimeUnit.MILLISECONDS); - private Long poolMaintenanceFrequencyMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() - .getMaintenanceFrequency(TimeUnit.MILLISECONDS); - /** * @param poolMaxSize * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxSize(int) */ - public void setPoolMaxSize(Integer poolMaxSize) { + public void setPoolMaxSize(int poolMaxSize) { this.poolMaxSize = poolMaxSize; } @@ -225,7 +241,7 @@ public void setPoolMaxSize(Integer poolMaxSize) { * @param poolMinSize * @see com.mongodb.connection.ConnectionPoolSettings.Builder#minSize(int) */ - public void setPoolMinSize(Integer poolMinSize) { + public void setPoolMinSize(int poolMinSize) { this.poolMinSize = poolMinSize; } @@ -233,7 +249,7 @@ public void setPoolMinSize(Integer poolMinSize) { * @param poolMaxWaitTimeMS in mesec * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxWaitTime(long, TimeUnit) */ - public void setPoolMaxWaitTimeMS(Long poolMaxWaitTimeMS) { + public void setPoolMaxWaitTimeMS(long poolMaxWaitTimeMS) { this.poolMaxWaitTimeMS = poolMaxWaitTimeMS; } @@ -241,7 +257,7 @@ public void setPoolMaxWaitTimeMS(Long poolMaxWaitTimeMS) { * @param poolMaxConnectionLifeTimeMS in msec * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxConnectionLifeTime(long, TimeUnit) */ - public void setPoolMaxConnectionLifeTimeMS(Long poolMaxConnectionLifeTimeMS) { + public void setPoolMaxConnectionLifeTimeMS(long poolMaxConnectionLifeTimeMS) { this.poolMaxConnectionLifeTimeMS = poolMaxConnectionLifeTimeMS; } @@ -249,7 +265,7 @@ public void setPoolMaxConnectionLifeTimeMS(Long poolMaxConnectionLifeTimeMS) { * @param poolMaxConnectionIdleTimeMS in msec * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxConnectionIdleTime(long, TimeUnit) */ - public void setPoolMaxConnectionIdleTimeMS(Long poolMaxConnectionIdleTimeMS) { + public void setPoolMaxConnectionIdleTimeMS(long poolMaxConnectionIdleTimeMS) { this.poolMaxConnectionIdleTimeMS = poolMaxConnectionIdleTimeMS; } @@ -257,7 +273,7 @@ public void setPoolMaxConnectionIdleTimeMS(Long poolMaxConnectionIdleTimeMS) { * @param poolMaintenanceInitialDelayMS in msec * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maintenanceInitialDelay(long, TimeUnit) */ - public void setPoolMaintenanceInitialDelayMS(Long poolMaintenanceInitialDelayMS) { + public void setPoolMaintenanceInitialDelayMS(long poolMaintenanceInitialDelayMS) { this.poolMaintenanceInitialDelayMS = poolMaintenanceInitialDelayMS; } @@ -265,18 +281,12 @@ public void setPoolMaintenanceInitialDelayMS(Long poolMaintenanceInitialDelayMS) * @param poolMaintenanceFrequencyMS in msec * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maintenanceFrequency(long, TimeUnit) */ - public void setPoolMaintenanceFrequencyMS(Long poolMaintenanceFrequencyMS) { + public void setPoolMaintenanceFrequencyMS(long poolMaintenanceFrequencyMS) { this.poolMaintenanceFrequencyMS = poolMaintenanceFrequencyMS; } // --> SSL Settings - private Boolean sslEnabled = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled(); - private Boolean sslInvalidHostNameAllowed = DEFAULT_MONGO_SETTINGS.getSslSettings().isInvalidHostNameAllowed(); - private String sslProvider = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled() - ? DEFAULT_MONGO_SETTINGS.getSslSettings().getContext().getProvider().getName() - : ""; - /** * @param sslEnabled * @see com.mongodb.connection.SslSettings.Builder#enabled(boolean) @@ -304,8 +314,6 @@ public void setSslProvider(String sslProvider) { // encryption and retry - private @Nullable AutoEncryptionSettings autoEncryptionSettings; - /** * @param applicationName * @see MongoClientSettings.Builder#applicationName(String) @@ -392,11 +400,11 @@ protected MongoClientSettings createInstance() { .readConcern(readConcern) // .codecRegistry(codecRegistry) // .applicationName(applicationName) // - .autoEncryptionSettings(autoEncryptionSettings)// + .autoEncryptionSettings(autoEncryptionSettings) // .applyToClusterSettings((settings) -> { settings.serverSelectionTimeout(clusterServerSelectionTimeoutMS, TimeUnit.MILLISECONDS); - if(clusterConnectionMode != null) { + if (clusterConnectionMode != null) { settings.mode(clusterConnectionMode); } settings.requiredReplicaSetName(clusterRequiredReplicaSetName); @@ -405,7 +413,7 @@ protected MongoClientSettings createInstance() { settings.hosts(clusterHosts); } settings.localThreshold(clusterLocalThresholdMS, TimeUnit.MILLISECONDS); -// settings.maxWaitQueueSize(clusterMaxWaitQueueSize); + // settings.maxWaitQueueSize(clusterMaxWaitQueueSize); settings.requiredClusterType(custerRequiredClusterType); if (StringUtils.hasText(clusterSrvHost)) { @@ -419,7 +427,7 @@ protected MongoClientSettings createInstance() { settings.maxConnectionIdleTime(poolMaxConnectionIdleTimeMS, TimeUnit.MILLISECONDS); settings.maxWaitTime(poolMaxWaitTimeMS, TimeUnit.MILLISECONDS); settings.maxConnectionLifeTime(poolMaxConnectionLifeTimeMS, TimeUnit.MILLISECONDS); -// settings.maxWaitQueueSize(poolMaxWaitQueueSize); + // settings.maxWaitQueueSize(poolMaxWaitQueueSize); settings.maintenanceFrequency(poolMaintenanceFrequencyMS, TimeUnit.MILLISECONDS); settings.maintenanceInitialDelay(poolMaintenanceInitialDelayMS, TimeUnit.MILLISECONDS); }) // @@ -430,19 +438,20 @@ protected MongoClientSettings createInstance() { }) // .applyToSocketSettings((settings) -> { - settings.connectTimeout(socketConnectTimeoutMS.intValue(), TimeUnit.MILLISECONDS); - settings.readTimeout(socketReadTimeoutMS.intValue(), TimeUnit.MILLISECONDS); + settings.connectTimeout(socketConnectTimeoutMS, TimeUnit.MILLISECONDS); + settings.readTimeout(socketReadTimeoutMS, TimeUnit.MILLISECONDS); settings.receiveBufferSize(socketReceiveBufferSize); settings.sendBufferSize(socketSendBufferSize); }) // .applyToSslSettings((settings) -> { settings.enabled(sslEnabled); - if (ObjectUtils.nullSafeEquals(Boolean.TRUE, sslEnabled)) { + if (sslEnabled) { settings.invalidHostNameAllowed(sslInvalidHostNameAllowed); try { - settings.context(StringUtils.hasText(sslProvider) ? SSLContext.getInstance(sslProvider) : SSLContext.getDefault()); + settings.context( + StringUtils.hasText(sslProvider) ? SSLContext.getInstance(sslProvider) : SSLContext.getDefault()); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e.getMessage(), e); } 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 cd441ae248..01a252b807 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 @@ -17,6 +17,7 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import com.mongodb.client.MongoClient; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NonNull; @@ -213,7 +214,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * @param databaseName must not be {@literal null} or empty. * @since 2.1 */ - public MongoTemplate(com.mongodb.client.MongoClient mongoClient, String databaseName) { + public MongoTemplate(MongoClient mongoClient, String databaseName) { this(new SimpleMongoClientDatabaseFactory(mongoClient, databaseName), (MongoConverter) null); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java index 43c3fd7379..c62bd5c54f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java @@ -21,6 +21,7 @@ * A factory bean for construction of a {@link MongoClientSettings} instance to be used with the async MongoDB driver. * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 * @deprecated since 3.0 - Use {@link MongoClientSettingsFactoryBean} instead. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 39ad590d99..5be87b5733 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -23,8 +23,6 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.DBObject; - /** * Holds a set of configurable aggregation options that can be used within an aggregation pipeline. A list of support * aggregation options can be found in the MongoDB reference documentation @@ -115,7 +113,7 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, int cursorBatch } /** - * Creates new {@link AggregationOptions} given {@link DBObject} containing aggregation options. + * Creates new {@link AggregationOptions} given {@link Document} containing aggregation options. * * @param document must not be {@literal null}. * @return the {@link AggregationOptions}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java index 596cdd8159..7cc656d54f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java @@ -26,7 +26,7 @@ import com.mongodb.DBObject; /** - * {@link IndexFilter} implementation for usage with plain {@link DBObject} as well as {@link CriteriaDefinition} filter + * {@link IndexFilter} implementation for usage with plain {@link Document} as well as {@link CriteriaDefinition} filter * expressions. * * @author Christoph Strobl @@ -38,7 +38,7 @@ public class PartialIndexFilter implements IndexFilter { private final @NonNull Object filterExpression; /** - * Create new {@link PartialIndexFilter} for given {@link DBObject filter expression}. + * Create new {@link PartialIndexFilter} for given {@link Document filter expression}. * * @param where must not be {@literal null}. * @return diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java index 446feb8e0e..0afd09f708 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java @@ -358,7 +358,7 @@ public MapReduceAction getMapReduceAction() { } /** - * @return {@literal true} if {@literal inline} output shall is used. + * @return {@literal true} if {@literal inline} output is used. * @since 2.0.10 */ public boolean usesInlineOutput() { diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index af0a45b371..1ebb3098c7 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -10,7 +10,8 @@ http\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.xsd=org/spri http\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-2.0.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-2.2.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd -http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-2.2.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo-3.0.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java index c2d5ce6bbd..4e6cfcc6bf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java @@ -140,5 +140,4 @@ public void clientWithConnectionPoolSettings() { assertThat(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)).isEqualTo(30); assertThat(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)).isEqualTo(15); } - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index 2824cd89a0..5113197cce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -204,8 +204,7 @@ public void testThirdGridFsTemplateFactory() { } @Test - @SuppressWarnings("deprecation") - public void testMongoSingletonWithPropertyPlaceHolders() throws Exception { + public void testMongoSingletonWithPropertyPlaceHolders() { assertThat(ctx.containsBean("mongoClient")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoClient"); @@ -215,20 +214,5 @@ public void testMongoSingletonWithPropertyPlaceHolders() throws Exception { assertThat(host).isEqualTo("127.0.0.1"); assertThat(port).isEqualTo(new Integer(27017)); - - // MongoClient mongo = mfb.getObject(); - // MongoClientSettings mongoOpts = mongo.getClusterDescription()..getMongoClientSettings(); - // - // assertThat(mongoOpts.getConnectionsPerHost()).isEqualTo(8); - // assertThat(mongoOpts.getConnectTimeout()).isEqualTo(1000); - // assertThat(mongoOpts.getMaxWaitTime()).isEqualTo(1500); - // - // assertThat(mongoOpts.getSocketTimeout()).isEqualTo(1500); - // assertThat(mongoOpts.getThreadsAllowedToBlockForConnectionMultiplier()).isEqualTo(4); - - // TODO: check the damned defaults - // assertEquals("w", mongoOpts.getWriteConcern().getW()); - // assertEquals(0, mongoOpts.getWriteConcern().getWtimeout()); - // assertEquals(true, mongoOpts.getWriteConcern().fsync()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java index fc9e3320fa..773f39dc62 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java @@ -1,19 +1,3 @@ -/* - * Copyright 2019. 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. - */ - /* * Copyright 2019 the original author or authors. * @@ -35,13 +19,15 @@ import java.util.concurrent.TimeUnit; -import com.mongodb.ServerAddress; import org.junit.jupiter.api.Test; import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; +import com.mongodb.ServerAddress; /** + * Unit tests for {@link MongoClientFactoryBean}. + * * @author Christoph Strobl */ class MongoClientFactoryBeanUnitTests { @@ -95,12 +81,12 @@ void explicitSettingsOverrideConnectionStringOnes() { } @Test // DATAMONGO-2427 - void hostAndPortPlusConnectionStringError() throws Exception { + void hostAndPortPlusConnectionStringError() { MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); factoryBean.setConnectionString(CONNECTION_STRING); factoryBean.setHost("localhost"); factoryBean.setPort(27017); - assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> factoryBean.createInstance()); + assertThatExceptionOfType(IllegalStateException.class).isThrownBy(factoryBean::createInstance); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java index 4b5cf6ddb0..ee93abf13a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java @@ -28,7 +28,7 @@ import com.mongodb.ReadPreference; /** - * Integration tests for {@link MongoClientSettingsFactoryBean}. + * Unit tests for {@link MongoClientSettingsFactoryBean}. * * @author Christoph Strobl */ 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 e10be32546..5404d7c000 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 @@ -79,6 +79,7 @@ public void appliesDocumentHintsCorrectly() { verify(cursor).hint(new Document("age", 1)); } + // TODO // @Test // DATAMONGO-957 // public void doesNotApplyMetaWhenEmpty() { // @@ -117,6 +118,7 @@ public void appliesCommentCorrectly() { verify(cursor).comment("spring data"); } + // TODO // @Test // DATAMONGO-957 // public void appliesSnapshotCorrectly() { // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java index 89da5de00f..794e407947 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java @@ -17,7 +17,6 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import static org.springframework.test.util.ReflectionTestUtils.*; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; @@ -26,6 +25,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.aop.framework.AopProxyUtils; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.test.util.ReflectionTestUtils; @@ -61,7 +61,6 @@ public void rejectsIllegalDatabaseNames() { } @Test // DATADOC-254 - @SuppressWarnings("deprecation") public void allowsDatabaseNames() { new SimpleMongoClientDatabaseFactory(mongo, "foo-bar"); new SimpleMongoClientDatabaseFactory(mongo, "foo_bar"); @@ -69,14 +68,13 @@ public void allowsDatabaseNames() { } @Test // DATADOC-295 - @SuppressWarnings("deprecation") public void mongoUriConstructor() { ConnectionString mongoURI = new ConnectionString( "mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); MongoDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(mongoURI); - assertThat(getField(mongoDbFactory, "databaseName").toString()).isEqualTo("myDatabase"); + assertThat(mongoDbFactory).hasFieldOrPropertyWithValue("databaseName", "myDatabase"); } @Test // DATAMONGO-1158 @@ -86,7 +84,7 @@ public void constructsMongoClientAccordingToMongoUri() { "mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(uri); - assertThat(getField(factory, "databaseName").toString()).isEqualTo("myDataBase"); + assertThat(factory).hasFieldOrPropertyWithValue("databaseName", "myDataBase"); } @Test // DATAMONGO-1880 diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 9b0a3d1ae2..afa253e62b 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -4,6 +4,7 @@ [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 +* Upgrade to MongoDB Driver 4.0. See <> for further details. * Support for <>. * Removal of `_id` flattening for composite Id's when using `MongoTemplate` aggregations. * Apply pagination when using GridFS `find(Query)`. diff --git a/src/main/asciidoc/preface.adoc b/src/main/asciidoc/preface.adoc index 448eb5414f..cd1a397a39 100644 --- a/src/main/asciidoc/preface.adoc +++ b/src/main/asciidoc/preface.adoc @@ -39,20 +39,23 @@ The starting point for learning about MongoDB is https://www.mongodb.org/[www.mo [[requirements]] == Requirements -The Spring Data MongoDB 2.x binaries require JDK level 8.0 and above and https://spring.io/docs[Spring Framework] {springVersion} and above. +The Spring Data MongoDB 3.x binaries require JDK level 8.0 and above and https://spring.io/docs[Spring Framework] {springVersion} and above. In terms of document stores, you need at least version 2.6 of https://www.mongodb.org/[MongoDB]. [[get-started:help]] == Additional Help Resources -Learning a new framework is not always straightforward. In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data MongoDB module. However, if you encounter issues or you need advice, feel free to use one of the following links: +Learning a new framework is not always straightforward. +In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data MongoDB module. +However, if you encounter issues or you need advice, feel free to use one of the following links: [[get-started:help:community]] -Community Forum :: Spring Data on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a tag for all Spring Data (not just Document) users to share information and help each other. Note that registration is needed only for posting. +Community Forum :: Spring Data on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a tag for all Spring Data (not just Document) users to share information and help each other. +Note that registration is needed only for posting. [[get-started:help:professional]] -Professional Support :: Professional, from-the-source support, with guaranteed response time, is available from https://pivotal.io/[Pivotal Sofware, Inc.], the company behind Spring Data and Spring. +Professional Support :: Professional, from-the-source support, with guaranteed response time, is available from https://pivotal.io/[Pivotal Software, Inc.], the company behind Spring Data and Spring. [[get-started:up-to-date]] == Following Development diff --git a/src/main/asciidoc/reference/client-session-transactions.adoc b/src/main/asciidoc/reference/client-session-transactions.adoc index 6343ae54e5..490ae8d195 100644 --- a/src/main/asciidoc/reference/client-session-transactions.adoc +++ b/src/main/asciidoc/reference/client-session-transactions.adoc @@ -185,10 +185,10 @@ The `MongoTransactionManager` binds a `ClientSession` to the thread. `MongoTempl [source,java] ---- @Configuration -static class Config extends AbstractMongoConfiguration { +static class Config extends AbstractMongoClientConfiguration { @Bean - MongoTransactionManager transactionManager(MongoDbFactory dbFactory) { <1> + MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { <1> return new MongoTransactionManager(dbFactory); } @@ -199,7 +199,7 @@ static class Config extends AbstractMongoConfiguration { public class StateService { @Transactional - void someBusinessFunction(Step step) { <2> + void someBusinessFunction(Step step) { <2> template.insert(step); diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 8aed432387..b034cdf674 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -278,7 +278,6 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { // the following are optional - @Bean @Override public CustomConversions customConversions() throws Exception { @@ -311,10 +310,9 @@ Spring's MongoDB namespace lets you enable mapping functionality in XML, as the @@ -769,7 +767,7 @@ To selectively handle the conversion yourself, register one or more one or more NOTE: Spring 3.0 introduced a core.convert package that provides a general type conversion system. This is described in detail in the Spring reference documentation section entitled https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#validation["`Spring Type Conversion`"]. -You can use the `customConversions` method in `AbstractMongoConfiguration` to configure converters. The examples <> show how to perform the configuration using Java and XML. +You can use the `customConversions` method in `AbstractMongoClientConfiguration` to configure converters. The examples <> show how to perform the configuration using Java and XML. The following example of a Spring Converter implementation converts from a `Document` to a `Person` POJO: diff --git a/src/main/asciidoc/reference/migrating.adoc b/src/main/asciidoc/reference/migrating.adoc index 81cfb0780c..0a82984879 100644 --- a/src/main/asciidoc/reference/migrating.adoc +++ b/src/main/asciidoc/reference/migrating.adoc @@ -13,8 +13,7 @@ This chapter coverts major changes and outlines migration steps. ** core-jar ** sync-jar - -This allows to include eg. just the reactive bits without having to pull in all the sync stuff. +The change in dependencies allows usage of the reactive support without having to pull the synchronous driver. NOTE: The new sync driver does no longer support `com.mongodb.DBObject`. Please use `org.bson.Document` instead. === Signature Changes @@ -22,7 +21,7 @@ NOTE: The new sync driver does no longer support `com.mongodb.DBObject`. Please * `MongoTemplate` no longer supports `com.mongodb.MongoClient` and `com.mongodb.MongoClientOptions`. Please use `com.mongodb.client.MongoClient` and `com.mongodb.MongoClientSettings` instead. -In case you're using `AbstractMongoConfiguration` please switch to `AbstractMongoClientInformation`. +In case you're using `AbstractMongoConfiguration` please switch to `AbstractMongoClientConfiguration`. === Namespace Changes diff --git a/src/main/asciidoc/reference/mongo-3.adoc b/src/main/asciidoc/reference/mongo-3.adoc index 04cc265fa5..2952edf477 100644 --- a/src/main/asciidoc/reference/mongo-3.adoc +++ b/src/main/asciidoc/reference/mongo-3.adoc @@ -1,12 +1,10 @@ [[mongo.mongo-3]] = MongoDB 3.0 Support -Spring Data MongoDB requires MongoDB Java driver generations 3 when connecting to a MongoDB 2.6/3.0 server running MMap.v1 or a MongoDB server 3.0 using MMap.v1 or the WiredTiger storage engine. +Spring Data MongoDB requires MongoDB Java driver generations 4 when connecting to a MongoDB 2.6/3.0 server running MMap.v1 or a MongoDB server 3.0 using MMap.v1 or the WiredTiger storage engine. NOTE: See the driver- and database-specific documentation for major differences between those engines. -NOTE: Operations that are no longer valid when using a 3.x MongoDB Java driver have been deprecated within Spring Data and will be removed in a subsequent release. - == Using Spring Data MongoDB with MongoDB 3.0 The rest of this section describes how to use Spring Data MongoDB with MongoDB 3.0. @@ -51,7 +49,7 @@ MongoDB Server generation 3 changed the authentication model when connecting to [source,java] ---- @Configuration -public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfiguration { +public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { @Override public String getDatabaseName() { @@ -118,11 +116,12 @@ NOTE: The field names used within the query expression are mapped to the domain [[mongo.mongo-3.misc]] === Miscellaneous Details -This section covers briefly lists additional things to keep in mind when using the 3.0 driver: +This section covers briefly lists additional things to keep in mind when using the 4.0 driver: * `IndexOperations.resetIndexCache()` is no longer supported. * Any `MapReduceOptions.extraOption` is silently ignored. * `WriteResult` no longer holds error information but, instead, throws an `Exception`. * `MongoOperations.executeInSession(…)` no longer calls `requestStart` and `requestDone`. -* Index name generation has become a driver-internal operation. Spring Data MongoDB still uses the 2.x schema to generate names. +* Index name generation has become a driver-internal operation. +Spring Data MongoDB still uses the 2.x schema to generate names. * Some `Exception` messages differ between the generation 2 and 3 servers as well as between the MMap.v1 and WiredTiger storage engines. diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index a97ccf93be..00f1493b6c 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -112,7 +112,7 @@ Because our domain repository extends `PagingAndSortingRepository`, it provides ==== [source,java] ---- -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class PersonRepositoryTests { @@ -601,7 +601,7 @@ class MongoTemplateProducer { @ApplicationScoped public MongoOperations createMongoTemplate() { - MongoDbFactory factory = new SimpleMongoClientDbFactory(MongoClients.create(), "database"); + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database"); return new MongoTemplate(factory); } } diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index b2d08d4531..7d849dfe13 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -165,7 +165,7 @@ There is a https://github.com/spring-projects/spring-data-examples[GitHub reposi [[mongodb-connectors]] == Connecting to MongoDB with Spring -One of the first tasks when using MongoDB and Spring is to create a `com.mongodb.client.MongoClient` or `com.mongodb.client.MongoClient` object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections. +One of the first tasks when using MongoDB and Spring is to create a `com.mongodb.client.MongoClient` object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections. NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.0.html#new-java-configuration[here] as well as the detailed documentation https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#beans-java-instantiating-container[here]. @@ -230,11 +230,9 @@ To use the Mongo namespace elements, you need to reference the Mongo schema, as @@ -281,21 +279,21 @@ The following example shows a configuration using replica sets: ==== [[mongo.mongo-db-factory]] -=== The MongoDbFactory Interface +=== The MongoDatabaseFactory Interface -While `com.mongodb.client.MongoClient` is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a `com.mongodb.client.MongoDatabase` object and access all the functionality of a specific MongoDB database instance. Spring provides the `org.springframework.data.mongodb.core.MongoDbFactory` interface, shown in the following listing, to bootstrap connectivity to the database: +While `com.mongodb.client.MongoClient` is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a `com.mongodb.client.MongoDatabase` object and access all the functionality of a specific MongoDB database instance. Spring provides the `org.springframework.data.mongodb.core.MongoDatabaseFactory` interface, shown in the following listing, to bootstrap connectivity to the database: [source,java] ---- -public interface MongoDbFactory { +public interface MongoDatabaseFactory { - MongoDatabase getDb() throws DataAccessException; + MongoDatabase getDatabase() throws DataAccessException; - MongoDatabase getDb(String dbName) throws DataAccessException; + MongoDatabase getDatabase(String dbName) throws DataAccessException; } ---- -The following sections show how you can use the container with either Java-based or XML-based metadata to configure an instance of the `MongoDbFactory` interface. In turn, you can use the `MongoDbFactory` instance to configure `MongoTemplate`. +The following sections show how you can use the container with either Java-based or XML-based metadata to configure an instance of the `MongoDatabaseFactory` interface. In turn, you can use the `MongoDatabaseFactory` instance to configure `MongoTemplate`. Instead of using the IoC container to create an instance of MongoTemplate, you can use them in standard Java code, as follows: @@ -307,7 +305,7 @@ public class MongoApp { public static void main(String[] args) throws Exception { - MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDbFactory(MongoClients.create(), "database")); + MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database")); mongoOps.insert(new Person("Joe", 34)); @@ -323,17 +321,17 @@ The code in bold highlights the use of `SimpleMongoClientDbFactory` and is the o NOTE: Use `SimpleMongoClientDbFactory` when choosing `com.mongodb.client.MongoClient` as the entrypoint of choice. [[mongo.mongo-db-factory-java]] -=== Registering a `MongoDbFactory` Instance by Using Java-based Metadata +=== Registering a `MongoDatabaseFactory` Instance by Using Java-based Metadata -To register a `MongoDbFactory` instance with the container, you write code much like what was highlighted in the previous code listing. The following listing shows a simple example: +To register a `MongoDatabaseFactory` instance with the container, you write code much like what was highlighted in the previous code listing. The following listing shows a simple example: [source,java] ---- @Configuration public class MongoConfiguration { - public @Bean MongoDbFactory mongoDbFactory() { - return new SimpleMongoClientDbFactory(MongoClients.create(), "database"); + public @Bean MongoDatabaseFactory mongoDatabaseFactory() { + return new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database"); } } ---- @@ -391,7 +389,7 @@ public class MongoClientConfiguration extends AbstractMongoClientConfiguration { ---- [[mongo.mongo-db-factory-xml]] -=== Registering a `MongoDbFactory` Instance by Using XML-based Metadata +=== Registering a `MongoDatabaseFactory` Instance by Using XML-based Metadata The `mongo` namespace provides a convenient way to create a `SimpleMongoClientDbFactory`, as compared to using the `` namespace, as shown in the following example: @@ -470,12 +468,12 @@ public class AppConfig { There are several overloaded constructors of `MongoTemplate`: * `MongoTemplate(MongoClient mongo, String databaseName)`: Takes the `MongoClient` object and the default database name to operate against. -* `MongoTemplate(MongoDbFactory mongoDbFactory)`: Takes a MongoDbFactory object that encapsulated the `MongoClient` object, database name, and username and password. -* `MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter)`: Adds a `MongoConverter` to use for mapping. +* `MongoTemplate(MongoDatabaseFactory mongoDbFactory)`: Takes a MongoDbFactory object that encapsulated the `MongoClient` object, database name, and username and password. +* `MongoTemplate(MongoDatabaseFactory mongoDbFactory, MongoConverter mongoConverter)`: Adds a `MongoConverter` to use for mapping. You can also configure a MongoTemplate by using Spring's XML schema, as the following example shows: -[source,java] +[source,xml] ---- @@ -3270,7 +3268,7 @@ boolean hasIndex = template.execute("geolocation", new CollectionCallbackBoolean [[gridfs]] == GridFS Support -MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a `GridFsOperations` interface as well as the corresponding implementation, `GridFsTemplate`, to let you interact with the filesystem. You can set up a `GridFsTemplate` instance by handing it a `MongoDbFactory` as well as a `MongoConverter`, as the following example shows: +MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a `GridFsOperations` interface as well as the corresponding implementation, `GridFsTemplate`, to let you interact with the filesystem. You can set up a `GridFsTemplate` instance by handing it a `MongoDatabaseFactory` as well as a `MongoConverter`, as the following example shows: .JavaConfig setup for a GridFsTemplate ==== diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index 4006d1d3ae..5077901320 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -1,4 +1,4 @@ -[[upgrading]] +[[upgrading.2-3]] = Upgrading from 2.x to 3.x Spring Data MongoDB 3.x requires the MongoDB Java Driver 4.x. + From f09c622b2f2035d981215c3592be05b26f0b5ba9 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 9 Jan 2020 13:13:41 +0100 Subject: [PATCH 0047/1381] DATAMONGO-2427 - Update GridFS API to use MongoDB native ByteBuffer Publisher API and introduce UUID format configuration options. Move from AsyncInputStream handling to Publisher for GridFS. UUID types require additional configuration setup to prevent errors while processing legacy (type 3) binary types. We still use type 3 as default but allow codec configuration for type 4 via Java and XML configuration. Updated migration guide. Original pull request: #823. --- README.adoc | 23 ++ .../data/mongodb/SpringDataMongoDB.java | 77 ++++ .../AbstractMongoClientConfiguration.java | 26 +- .../AbstractReactiveMongoConfiguration.java | 23 +- .../mongodb/config/MongoClientParser.java | 4 + .../config/MongoConfigurationSupport.java | 28 ++ .../mongodb/config/MongoParsingUtils.java | 19 + .../UUidRepresentationPropertyEditor.java | 45 +++ .../mongodb/core/MongoClientFactoryBean.java | 7 +- .../core/MongoClientSettingsFactoryBean.java | 15 +- .../gridfs/AsyncInputStreamAdapter.java | 361 ------------------ .../mongodb/gridfs/BinaryStreamAdapters.java | 80 ---- .../gridfs/DataBufferPublisherAdapter.java | 340 ----------------- .../gridfs/ReactiveGridFsOperations.java | 28 -- .../gridfs/ReactiveGridFsResource.java | 158 ++------ .../gridfs/ReactiveGridFsTemplate.java | 53 ++- .../query/StringBasedMongoQuery.java | 15 +- .../data/mongodb/config/spring-mongo-3.0.xsd | 20 + .../data/mongodb/SpringDataMongoDBTests.java | 36 ++ .../config/MongoClientNamespaceTests.java | 12 + .../config/MongoParserIntegrationTests.java | 1 - ...ngoClientSettingsFactoryBeanUnitTests.java | 17 + .../data/mongodb/core/MongoTemplateTests.java | 1 + .../gridfs/BinaryStreamAdaptersUnitTests.java | 103 ----- .../DataBufferPublisherAdapterUnitTests.java | 55 --- .../gridfs/ReactiveGridFsTemplateTests.java | 103 ++++- .../query/StringBasedMongoQueryUnitTests.java | 51 ++- .../mongodb/test/util/MongoTestUtils.java | 10 +- .../MongoClientNamespaceTests-context.xml | 4 + src/main/asciidoc/upgrading.adoc | 26 ++ 30 files changed, 579 insertions(+), 1162 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SpringDataMongoDBTests.java delete mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java delete mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java diff --git a/README.adoc b/README.adoc index 820ace0073..cbd524c70e 100644 --- a/README.adoc +++ b/README.adoc @@ -208,6 +208,29 @@ Uses `MongoClientSettings` instead of `MongoClientOptions`. | |=== +=== Other Changes + +==== UUID Types + +The MongoDB UUID representation can now be configured with different formats. +This has to be done via `MongoClientSettings` as shown in the snippet below. + +.UUID Codec Configuration +==== +[source,java] +---- +static class Config extends AbstractMongoClientConfiguration { + + @Override + public void configureClientSettings(MongoClientSettings.Builder builder) { + builder.uuidRepresentation(UuidRepresentation.STANDARD); + } + + // ... +} +---- +==== + == Getting Help Having trouble with Spring Data? We’d love to help! diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java new file mode 100644 index 0000000000..cc3004644f --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java @@ -0,0 +1,77 @@ +/* + * Copyright 2020 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 + * + * https://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; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.util.Version; +import org.springframework.util.StringUtils; + +import com.mongodb.MongoDriverInformation; + +/** + * Class that exposes the SpringData MongoDB specific information like the current {@link Version} or + * {@link MongoDriverInformation driver information}. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class SpringDataMongoDB { + + private static final Logger LOGGER = LoggerFactory.getLogger(SpringDataMongoDB.class); + + private static final Version FALLBACK_VERSION = new Version(3); + private static final MongoDriverInformation DRIVER_INFORMATION = MongoDriverInformation + .builder(MongoDriverInformation.builder().build()).driverName("spring-data").build(); + + /** + * Obtain the SpringData MongoDB specific driver information. + * + * @return never {@literal null}. + */ + public static MongoDriverInformation driverInformation() { + return DRIVER_INFORMATION; + } + + /** + * Fetches the "Implementation-Version" manifest attribute from the jar file. + *

      + * Note that some ClassLoaders do not expose the package metadata, hence this class might not be able to determine the + * version in all environments. In this case the current Major version is returned as a fallback. + * + * @return never {@literal null}. + */ + public static Version version() { + + Package pkg = SpringDataMongoDB.class.getPackage(); + String versionString = (pkg != null ? pkg.getImplementationVersion() : null); + + if (!StringUtils.hasText(versionString)) { + + LOGGER.debug("Unable to find Spring Data MongoDB version."); + return FALLBACK_VERSION; + } + + try { + return Version.parse(versionString); + } catch (Exception e) { + LOGGER.debug("Cannot read Spring Data MongoDB version '{}'.", versionString); + } + + return FALLBACK_VERSION; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index cce5714985..2bac4e54a0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -15,9 +15,11 @@ */ package org.springframework.data.mongodb.config; +import com.mongodb.MongoClientSettings.Builder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.SpringDataMongoDB; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -26,7 +28,9 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.lang.Nullable; +import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; /** * Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.client.MongoClient}. @@ -40,11 +44,16 @@ public abstract class AbstractMongoClientConfiguration extends MongoConfiguratio /** * Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a - * {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}. + * {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
      + * Override {@link #mongoClientSettings()} to configure connection details. * - * @return + * @return never {@literal null}. + * @see #mongoClientSettings() + * @see #configureClientSettings(Builder) */ - public abstract MongoClient mongoClient(); + public MongoClient mongoClient() { + return createMongoClient(mongoClientSettings()); + } /** * Creates a {@link MongoTemplate}. @@ -107,4 +116,15 @@ public MappingMongoConverter mappingMongoConverter() throws Exception { return converter; } + + /** + * Create the Reactive Streams {@link com.mongodb.reactivestreams.client.MongoClient} instance with given + * {@link MongoClientSettings}. + * + * @return never {@literal null}. + * @since 3.0 + */ + protected MongoClient createMongoClient(MongoClientSettings settings) { + return MongoClients.create(settings, SpringDataMongoDB.driverInformation()); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java index 2e550dfba8..d64bcfc914 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java @@ -18,13 +18,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.SpringDataMongoDB; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; import com.mongodb.reactivestreams.client.MongoClient; +import com.mongodb.reactivestreams.client.MongoClients; /** * Base class for reactive Spring Data MongoDB configuration using JavaConfig. @@ -39,11 +43,16 @@ public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurat /** * Return the Reactive Streams {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want - * to expose a {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}. + * to expose a {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
      + * Override {@link #mongoClientSettings()} to configure connection details. * * @return never {@literal null}. + * @see #mongoClientSettings() + * @see #configureClientSettings(Builder) */ - public abstract MongoClient reactiveMongoClient(); + public MongoClient reactiveMongoClient() { + return createReactiveMongoClient(mongoClientSettings()); + } /** * Creates {@link ReactiveMongoOperations}. @@ -87,4 +96,14 @@ public MappingMongoConverter mappingMongoConverter() throws Exception { return converter; } + + /** + * Create the Reactive Streams {@link MongoClient} instance with given {@link MongoClientSettings}. + * + * @return never {@literal null}. + * @since 3.0 + */ + protected MongoClient createReactiveMongoClient(MongoClientSettings settings) { + return MongoClients.create(settings, SpringDataMongoDB.driverInformation()); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java index b6e13d8568..b3dcfdabce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java @@ -87,6 +87,10 @@ public BeanDefinition parse(Element element, ParserContext parserContext) { .getComponent(MongoParsingUtils.getMongoCredentialPropertyEditor()); parserContext.registerBeanComponent(credentialsEditor); + BeanComponentDefinition uuidRepresentationEditor = helper + .getComponent(MongoParsingUtils.getUUidRepresentationEditorBuilder()); + parserContext.registerBeanComponent(uuidRepresentationEditor); + parserContext.popAndRegisterContainingComponent(); return mongoComponent.getBeanDefinition(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index ea137756f9..a616467838 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -20,6 +20,7 @@ import java.util.HashSet; import java.util.Set; +import org.bson.UuidRepresentation; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; @@ -36,6 +37,9 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; + /** * Base class for Spring Data MongoDB to be extended for JavaConfiguration usage. * @@ -184,4 +188,28 @@ protected FieldNamingStrategy fieldNamingStrategy() { protected boolean autoIndexCreation() { return true; } + + /** + * Return the {@link MongoClientSettings} used to create the actual {@literal MongoClient}.
      + * Override either this method, or use {@link #configureClientSettings(Builder)} to alter the setup. + * + * @return never {@literal null}. + * @since 3.0 + */ + protected MongoClientSettings mongoClientSettings() { + + MongoClientSettings.Builder builder = MongoClientSettings.builder(); + configureClientSettings(builder); + return builder.build(); + } + + /** + * Configure {@link MongoClientSettings} via its {@link Builder} API. + * + * @param builder never {@literal null}. + * @since 3.0 + */ + protected void configureClientSettings(MongoClientSettings.Builder builder) { + builder.uuidRepresentation(UuidRepresentation.JAVA_LEGACY); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index 96d6a23200..7ed91b27f9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -67,6 +67,7 @@ public static boolean parseMongoClientSettings(Element element, BeanDefinitionBu setPropertyValue(clientOptionsDefBuilder, settingsElement, "write-concern", "writeConcern"); setPropertyValue(clientOptionsDefBuilder, settingsElement, "retry-reads", "retryReads"); setPropertyValue(clientOptionsDefBuilder, settingsElement, "retry-writes", "retryWrites"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "uuid-representation", "uUidRepresentation"); // SocketSettings setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-connect-timeout", "socketConnectTimeoutMS"); @@ -223,4 +224,22 @@ static BeanDefinitionBuilder getConnectionStringPropertyEditorBuilder() { return builder; } + /** + * Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a + * {@link ConnectionStringPropertyEditor}. + * + * @return + * @since 3.0 + */ + static BeanDefinitionBuilder getUUidRepresentationEditorBuilder() { + + Map> customEditors = new ManagedMap<>(); + customEditors.put("org.bson.UuidRepresentation", UUidRepresentationPropertyEditor.class); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); + builder.addPropertyValue("customEditors", customEditors); + + return builder; + } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java new file mode 100644 index 0000000000..2499ecc48b --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2020 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 + * + * https://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.config; + +import java.beans.PropertyEditorSupport; + +import org.bson.UuidRepresentation; +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +/** + * Parse a {@link String} to a {@link UuidRepresentation}. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class UUidRepresentationPropertyEditor extends PropertyEditorSupport { + + /* + * (non-Javadoc) + * @see java.beans.PropertyEditorSupport#setAsText(java.lang.String) + */ + @Override + public void setAsText(@Nullable String value) { + + if (!StringUtils.hasText(value)) { + return; + } + + setValue(UuidRepresentation.valueOf(value)); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index d4ec1f5d82..7c281c7bf6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -23,9 +23,11 @@ import java.util.function.Function; import java.util.stream.Collectors; +import org.bson.UuidRepresentation; import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.mongodb.SpringDataMongoDB; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -164,6 +166,7 @@ protected MongoClientSettings computeClientSetting() { getOrDefault(port, "" + ServerAddress.defaultPort()))); Builder builder = MongoClientSettings.builder().applyConnectionString(connectionString); + builder.uuidRepresentation(UuidRepresentation.JAVA_LEGACY); if (mongoClientSettings != null) { @@ -291,6 +294,8 @@ protected MongoClientSettings computeClientSetting() { mongoClientSettings.getRetryReads(), connectionString.getRetryReads())); applySettings(builder::retryWrites, computeSettingsValue(defaultSettings.getRetryWrites(), mongoClientSettings.getRetryWrites(), connectionString.getRetryWritesValue())); + applySettings(builder::uuidRepresentation, + computeSettingsValue(null, mongoClientSettings.getUuidRepresentation(), UuidRepresentation.JAVA_LEGACY)); } if (!CollectionUtils.isEmpty(credential)) { @@ -344,7 +349,7 @@ protected void destroyInstance(@Nullable MongoClient instance) throws Exception } private MongoClient createMongoClient(MongoClientSettings settings) throws UnknownHostException { - return MongoClients.create(settings); + return MongoClients.create(settings, SpringDataMongoDB.driverInformation()); } private String getOrDefault(Object value, String defaultValue) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java index f8cf254cb3..2c66fe3813 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java @@ -23,8 +23,8 @@ import javax.net.ssl.SSLContext; +import org.bson.UuidRepresentation; import org.bson.codecs.configuration.CodecRegistry; - import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; @@ -64,6 +64,8 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean Socket Settings private int socketConnectTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() @@ -378,6 +380,13 @@ public void setCodecRegistry(CodecRegistry codecRegistry) { this.codecRegistry = codecRegistry; } + /** + * @param uUidRepresentation + */ + public void setuUidRepresentation(@Nullable UuidRepresentation uUidRepresentation) { + this.uUidRepresentation = uUidRepresentation; + } + /** * @param autoEncryptionSettings can be {@literal null}. * @see MongoClientSettings.Builder#autoEncryptionSettings(AutoEncryptionSettings) @@ -468,6 +477,10 @@ protected MongoClientSettings createInstance() { builder = builder.retryWrites(retryWrites); } + if (uUidRepresentation != null) { + builder.uuidRepresentation(uUidRepresentation); + } + return builder.build(); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java deleted file mode 100644 index 62514484f8..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright 2019-2020 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 - * - * https://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.gridfs; - -import lombok.RequiredArgsConstructor; -import reactor.core.CoreSubscriber; -import reactor.core.publisher.Flux; -import reactor.core.publisher.FluxSink; -import reactor.core.publisher.Mono; -import reactor.core.publisher.Operators; -import reactor.util.concurrent.Queues; -import reactor.util.context.Context; - -import java.nio.ByteBuffer; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscription; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; - -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; - -/** - * Adapter accepting a binary stream {@link Publisher} and emitting its through {@link AsyncInputStream}. - *

      - * This adapter subscribes to the binary {@link Publisher} as soon as the first chunk gets {@link #read(ByteBuffer) - * requested}. Requests are queued and binary chunks are requested from the {@link Publisher}. As soon as the - * {@link Publisher} emits items, chunks are provided to the read request which completes the number-of-written-bytes - * {@link Publisher}. - *

      - * {@link AsyncInputStream} is supposed to work as sequential callback API that is called until reaching EOF. - * {@link #close()} is propagated as cancellation signal to the binary {@link Publisher}. - * - * @author Mark Paluch - * @author Christoph Strobl - * @since 2.2 - */ -@RequiredArgsConstructor -class AsyncInputStreamAdapter implements AsyncInputStream { - - private static final AtomicLongFieldUpdater DEMAND = AtomicLongFieldUpdater - .newUpdater(AsyncInputStreamAdapter.class, "demand"); - - private static final AtomicIntegerFieldUpdater SUBSCRIBED = AtomicIntegerFieldUpdater - .newUpdater(AsyncInputStreamAdapter.class, "subscribed"); - - private static final int SUBSCRIPTION_NOT_SUBSCRIBED = 0; - private static final int SUBSCRIPTION_SUBSCRIBED = 1; - - private final Publisher buffers; - private final Context subscriberContext; - - private volatile Subscription subscription; - private volatile boolean cancelled; - private volatile boolean allDataBuffersReceived; - private volatile Throwable error; - private final Queue readRequests = Queues. small().get(); - - private final Queue bufferQueue = Queues. small().get(); - - // see DEMAND - volatile long demand; - - // see SUBSCRIBED - volatile int subscribed = SUBSCRIPTION_NOT_SUBSCRIBED; - - /* - * (non-Javadoc) - * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#read(java.nio.ByteBuffer) - */ - @Override - public Publisher read(ByteBuffer dst) { - - return Flux.create(sink -> { - - readRequests.offer(new ReadRequest(sink, dst)); - - sink.onCancel(this::terminatePendingReads); - sink.onDispose(this::terminatePendingReads); - sink.onRequest(this::request); - }); - } - - void onError(FluxSink sink, Throwable e) { - - readRequests.poll(); - sink.error(e); - } - - void onComplete(FluxSink sink, int writtenBytes) { - - readRequests.poll(); - DEMAND.decrementAndGet(this); - sink.next(writtenBytes); - sink.complete(); - } - - /* - * (non-Javadoc) - * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#skip(long) - */ - @Override - public Publisher skip(long bytesToSkip) { - throw new UnsupportedOperationException("Skip is currently not implemented"); - } - - /* - * (non-Javadoc) - * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#close() - */ - @Override - public Publisher close() { - - return Mono.create(sink -> { - - cancelled = true; - - if (error != null) { - terminatePendingReads(); - sink.error(error); - return; - } - - terminatePendingReads(); - sink.success(); - }); - } - - protected void request(long n) { - - if (allDataBuffersReceived && bufferQueue.isEmpty()) { - - terminatePendingReads(); - return; - } - - Operators.addCap(DEMAND, this, n); - - if (SUBSCRIBED.get(this) == SUBSCRIPTION_NOT_SUBSCRIBED) { - - if (SUBSCRIBED.compareAndSet(this, SUBSCRIPTION_NOT_SUBSCRIBED, SUBSCRIPTION_SUBSCRIBED)) { - buffers.subscribe(new DataBufferCoreSubscriber()); - } - - } else { - - Subscription subscription = this.subscription; - - if (subscription != null) { - requestFromSubscription(subscription); - } - } - - } - - void requestFromSubscription(Subscription subscription) { - - if (cancelled) { - subscription.cancel(); - } - - drainLoop(); - } - - void drainLoop() { - - while (DEMAND.get(AsyncInputStreamAdapter.this) > 0) { - - DataBuffer wip = bufferQueue.peek(); - - if (wip == null) { - break; - } - - if (wip.readableByteCount() == 0) { - bufferQueue.poll(); - continue; - } - - ReadRequest consumer = AsyncInputStreamAdapter.this.readRequests.peek(); - if (consumer == null) { - break; - } - - consumer.transferBytes(wip, wip.readableByteCount()); - } - - if (bufferQueue.isEmpty()) { - - if (allDataBuffersReceived) { - terminatePendingReads(); - return; - } - - if (demand > 0) { - subscription.request(1); - } - } - } - - /** - * Terminates pending reads with empty buffers. - */ - void terminatePendingReads() { - - ReadRequest readers; - - while ((readers = readRequests.poll()) != null) { - readers.onComplete(); - } - } - - private class DataBufferCoreSubscriber implements CoreSubscriber { - - @Override - public Context currentContext() { - return AsyncInputStreamAdapter.this.subscriberContext; - } - - @Override - public void onSubscribe(Subscription s) { - - AsyncInputStreamAdapter.this.subscription = s; - s.request(1); - } - - @Override - public void onNext(DataBuffer dataBuffer) { - - if (cancelled || allDataBuffersReceived) { - DataBufferUtils.release(dataBuffer); - Operators.onNextDropped(dataBuffer, AsyncInputStreamAdapter.this.subscriberContext); - return; - } - - ReadRequest readRequest = AsyncInputStreamAdapter.this.readRequests.peek(); - - if (readRequest == null) { - - DataBufferUtils.release(dataBuffer); - Operators.onNextDropped(dataBuffer, AsyncInputStreamAdapter.this.subscriberContext); - subscription.cancel(); - return; - } - - bufferQueue.offer(dataBuffer); - - drainLoop(); - } - - @Override - public void onError(Throwable t) { - - if (AsyncInputStreamAdapter.this.cancelled || AsyncInputStreamAdapter.this.allDataBuffersReceived) { - Operators.onErrorDropped(t, AsyncInputStreamAdapter.this.subscriberContext); - return; - } - - AsyncInputStreamAdapter.this.error = t; - AsyncInputStreamAdapter.this.allDataBuffersReceived = true; - terminatePendingReads(); - } - - @Override - public void onComplete() { - - AsyncInputStreamAdapter.this.allDataBuffersReceived = true; - if (bufferQueue.isEmpty()) { - terminatePendingReads(); - } - } - } - - /** - * Request to read bytes and transfer these to the associated {@link ByteBuffer}. - */ - class ReadRequest { - - private final FluxSink sink; - private final ByteBuffer dst; - - private int writtenBytes; - - ReadRequest(FluxSink sink, ByteBuffer dst) { - this.sink = sink; - this.dst = dst; - this.writtenBytes = -1; - } - - public void onComplete() { - - if (error != null) { - AsyncInputStreamAdapter.this.onError(sink, error); - return; - } - - AsyncInputStreamAdapter.this.onComplete(sink, writtenBytes); - } - - public void transferBytes(DataBuffer db, int bytes) { - - try { - - if (error != null) { - AsyncInputStreamAdapter.this.onError(sink, error); - return; - } - - ByteBuffer byteBuffer = db.asByteBuffer(); - int remaining = byteBuffer.remaining(); - int writeCapacity = Math.min(dst.remaining(), remaining); - int limit = Math.min(byteBuffer.position() + writeCapacity, byteBuffer.capacity()); - int toWrite = limit - byteBuffer.position(); - - if (toWrite == 0) { - - AsyncInputStreamAdapter.this.onComplete(sink, writtenBytes); - return; - } - - int oldPosition = byteBuffer.position(); - - byteBuffer.limit(toWrite); - dst.put(byteBuffer); - byteBuffer.limit(byteBuffer.capacity()); - byteBuffer.position(oldPosition); - db.readPosition(db.readPosition() + toWrite); - - if (writtenBytes == -1) { - writtenBytes = bytes; - } else { - writtenBytes += bytes; - } - - } catch (Exception e) { - AsyncInputStreamAdapter.this.onError(sink, e); - } finally { - - if (db.readableByteCount() == 0) { - DataBufferUtils.release(db); - } - } - } - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java deleted file mode 100644 index e793f84c19..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdapters.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019-2020 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 - * - * https://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.gridfs; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.reactivestreams.Publisher; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.core.io.buffer.DataBufferUtils; - -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; - -/** - * Utility methods to create adapters from between {@link Publisher} of {@link DataBuffer} and {@link AsyncInputStream}. - * - * @author Mark Paluch - * @since 2.2 - */ -class BinaryStreamAdapters { - - /** - * Creates a {@link Flux} emitting {@link DataBuffer} by reading binary chunks from {@link AsyncInputStream}. - * Publisher termination (completion, error, cancellation) closes the {@link AsyncInputStream}. - *

      - * The resulting {@link org.reactivestreams.Publisher} filters empty binary chunks and uses {@link DataBufferFactory} - * settings to determine the chunk size. - * - * @param inputStream must not be {@literal null}. - * @param dataBufferFactory must not be {@literal null}. - * @param bufferSize read {@code n} bytes per iteration. - * @return {@link Flux} emitting {@link DataBuffer}s. - * @see DataBufferFactory#allocateBuffer() - */ - static Flux toPublisher(AsyncInputStream inputStream, DataBufferFactory dataBufferFactory, - int bufferSize) { - - return DataBufferPublisherAdapter.createBinaryStream(inputStream, dataBufferFactory, bufferSize) // - .filter(it -> { - - if (it.readableByteCount() == 0) { - DataBufferUtils.release(it); - return false; - } - return true; - }); - } - - /** - * Creates a {@link Mono} emitting a {@link AsyncInputStream} to consume a {@link Publisher} emitting - * {@link DataBuffer} and exposing the binary stream through {@link AsyncInputStream}. {@link DataBuffer}s are - * released by the adapter during consumption. - *

      - * This method returns a {@link Mono} to retain the {@link reactor.util.context.Context subscriber context}. - * - * @param dataBuffers must not be {@literal null}. - * @return {@link Mono} emitting {@link AsyncInputStream}. - * @see DataBufferUtils#release(DataBuffer) - */ - static Mono toAsyncInputStream(Publisher dataBuffers) { - - return Mono.create(sink -> { - sink.success(new AsyncInputStreamAdapter(dataBuffers, sink.currentContext())); - }); - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java deleted file mode 100644 index 359d0fb05c..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright 2019-2020 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 - * - * https://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.gridfs; - -import lombok.RequiredArgsConstructor; -import reactor.core.CoreSubscriber; -import reactor.core.publisher.Flux; -import reactor.core.publisher.FluxSink; -import reactor.core.publisher.Mono; -import reactor.core.publisher.Operators; -import reactor.util.context.Context; - -import java.nio.ByteBuffer; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscription; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; - -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; - -/** - * Utility to adapt a {@link AsyncInputStream} to a {@link Publisher} emitting {@link DataBuffer}. - * - * @author Mark Paluch - * @author Christoph Strobl - * @since 2.2 - */ -class DataBufferPublisherAdapter { - - /** - * Creates a {@link Publisher} emitting {@link DataBuffer}s by reading binary chunks from {@link AsyncInputStream}. - * Closes the {@link AsyncInputStream} once the {@link Publisher} terminates. - * - * @param inputStream must not be {@literal null}. - * @param dataBufferFactory must not be {@literal null}. - * @param bufferSize read {@code n} bytes per iteration. - * @return the resulting {@link Publisher}. - */ - static Flux createBinaryStream(AsyncInputStream inputStream, DataBufferFactory dataBufferFactory, - int bufferSize) { - - return Flux.usingWhen(Mono.just(new DelegatingAsyncInputStream(inputStream, dataBufferFactory, bufferSize)), - DataBufferPublisherAdapter::doRead, AsyncInputStream::close, (it, err) -> it.close(), AsyncInputStream::close); - } - - /** - * Use an {@link AsyncInputStreamHandler} to read data from the given {@link AsyncInputStream}. - * - * @param inputStream the source stream. - * @return a {@link Flux} emitting data chunks one by one. - * @since 2.2.1 - */ - private static Flux doRead(DelegatingAsyncInputStream inputStream) { - - AsyncInputStreamHandler streamHandler = new AsyncInputStreamHandler(inputStream, inputStream.dataBufferFactory, - inputStream.bufferSize); - return Flux.create((sink) -> { - - sink.onDispose(streamHandler::close); - sink.onCancel(streamHandler::close); - - sink.onRequest(n -> { - streamHandler.request(sink, n); - }); - }); - } - - /** - * An {@link AsyncInputStream} also holding a {@link DataBufferFactory} and default {@literal bufferSize} for reading - * from it, delegating operations on the {@link AsyncInputStream} to the reference instance.
      - * Used to pass on the {@link AsyncInputStream} and parameters to avoid capturing lambdas. - * - * @author Christoph Strobl - * @since 2.2.1 - */ - private static class DelegatingAsyncInputStream implements AsyncInputStream { - - private final AsyncInputStream inputStream; - private final DataBufferFactory dataBufferFactory; - private int bufferSize; - - /** - * @param inputStream the source input stream. - * @param dataBufferFactory - * @param bufferSize - */ - DelegatingAsyncInputStream(AsyncInputStream inputStream, DataBufferFactory dataBufferFactory, int bufferSize) { - - this.inputStream = inputStream; - this.dataBufferFactory = dataBufferFactory; - this.bufferSize = bufferSize; - } - - /* - * (non-Javadoc) - * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#read(java.nio.ByteBuffer) - */ - @Override - public Publisher read(ByteBuffer dst) { - return inputStream.read(dst); - } - - /* - * (non-Javadoc) - * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#skip(long) - */ - @Override - public Publisher skip(long bytesToSkip) { - return inputStream.skip(bytesToSkip); - } - - /* - * (non-Javadoc) - * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#close() - */ - @Override - public Publisher close() { - return inputStream.close(); - } - } - - @RequiredArgsConstructor - static class AsyncInputStreamHandler { - - private static final AtomicLongFieldUpdater DEMAND = AtomicLongFieldUpdater - .newUpdater(AsyncInputStreamHandler.class, "demand"); - - private static final AtomicIntegerFieldUpdater STATE = AtomicIntegerFieldUpdater - .newUpdater(AsyncInputStreamHandler.class, "state"); - - private static final AtomicIntegerFieldUpdater DRAIN = AtomicIntegerFieldUpdater - .newUpdater(AsyncInputStreamHandler.class, "drain"); - - private static final AtomicIntegerFieldUpdater READ = AtomicIntegerFieldUpdater - .newUpdater(AsyncInputStreamHandler.class, "read"); - - private static final int STATE_OPEN = 0; - private static final int STATE_CLOSED = 1; - - private static final int DRAIN_NONE = 0; - private static final int DRAIN_COMPLETION = 1; - - private static final int READ_NONE = 0; - private static final int READ_IN_PROGRESS = 1; - - final AsyncInputStream inputStream; - final DataBufferFactory dataBufferFactory; - final int bufferSize; - - // see DEMAND - volatile long demand; - - // see STATE - volatile int state = STATE_OPEN; - - // see DRAIN - volatile int drain = DRAIN_NONE; - - // see READ_IN_PROGRESS - volatile int read = READ_NONE; - - void request(FluxSink sink, long n) { - - Operators.addCap(DEMAND, this, n); - drainLoop(sink); - } - - /** - * Loops while we have demand and while no read is in progress. - * - * @param sink - */ - void drainLoop(FluxSink sink) { - while (onShouldRead()) { - emitNext(sink); - } - } - - boolean onShouldRead() { - return !isClosed() && getDemand() > 0 && onWantRead(); - } - - boolean onWantRead() { - return READ.compareAndSet(this, READ_NONE, READ_IN_PROGRESS); - } - - void onReadDone() { - READ.compareAndSet(this, READ_IN_PROGRESS, READ_NONE); - } - - long getDemand() { - return DEMAND.get(this); - } - - void decrementDemand() { - DEMAND.decrementAndGet(this); - } - - void close() { - STATE.compareAndSet(this, STATE_OPEN, STATE_CLOSED); - } - - boolean enterDrainLoop() { - return DRAIN.compareAndSet(this, DRAIN_NONE, DRAIN_COMPLETION); - } - - void leaveDrainLoop() { - DRAIN.set(this, DRAIN_NONE); - } - - boolean isClosed() { - return STATE.get(this) == STATE_CLOSED; - } - - /** - * Emit the next {@link DataBuffer}. - * - * @param sink - * @return - */ - private void emitNext(FluxSink sink) { - - ByteBuffer transport = ByteBuffer.allocate(bufferSize); - BufferCoreSubscriber bufferCoreSubscriber = new BufferCoreSubscriber(sink, dataBufferFactory, transport); - try { - inputStream.read(transport).subscribe(bufferCoreSubscriber); - } catch (Throwable e) { - sink.error(e); - } - } - - private class BufferCoreSubscriber implements CoreSubscriber { - - private final FluxSink sink; - private final DataBufferFactory factory; - private final ByteBuffer transport; - private volatile Subscription subscription; - - BufferCoreSubscriber(FluxSink sink, DataBufferFactory factory, ByteBuffer transport) { - - this.sink = sink; - this.factory = factory; - this.transport = transport; - } - - @Override - public Context currentContext() { - return sink.currentContext(); - } - - @Override - public void onSubscribe(Subscription s) { - - this.subscription = s; - s.request(1); - } - - @Override - public void onNext(Integer bytes) { - - if (isClosed()) { - return; - } - - if (bytes > 0) { - - DataBuffer buffer = readNextChunk(); - sink.next(buffer); - decrementDemand(); - } - - if (bytes == -1) { - sink.complete(); - return; - } - - subscription.request(1); - } - - private DataBuffer readNextChunk() { - - transport.flip(); - - DataBuffer dataBuffer = factory.allocateBuffer(transport.remaining()); - dataBuffer.write(transport); - - transport.clear(); - - return dataBuffer; - } - - @Override - public void onError(Throwable t) { - - if (isClosed()) { - - Operators.onErrorDropped(t, sink.currentContext()); - return; - } - - close(); - sink.error(t); - } - - @Override - public void onComplete() { - - onReadDone(); - - if (!isClosed()) { - - if (enterDrainLoop()) { - try { - drainLoop(sink); - } finally { - leaveDrainLoop(); - } - } - - } - } - } - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java index 9170da7cc5..f189ea9d85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java @@ -27,7 +27,6 @@ import org.springframework.lang.Nullable; import com.mongodb.client.gridfs.model.GridFSFile; -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; /** * Collection of operations to store and read files from MongoDB GridFS using reactive infrastructure. @@ -101,20 +100,6 @@ default Mono store(Publisher content, @Nullable String fil return store(content, filename, null, metadata); } - /** - * Stores the given content into a file with the given name and content type using the given metadata. The metadata - * object will be marshalled before writing. - * - * @param content must not be {@literal null}. - * @param filename must not be {@literal null} or empty. - * @param contentType can be {@literal null}. - * @param metadata can be {@literal null} - * @return a {@link Mono} emitting the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just - * created. - */ - Mono store(AsyncInputStream content, @Nullable String filename, @Nullable String contentType, - @Nullable Object metadata); - /** * Stores the given content into a file with the given name and content type using the given metadata. The metadata * object will be marshalled before writing. @@ -142,19 +127,6 @@ default Mono store(Publisher content, @Nullable String fil return store(content, filename, null, metadata); } - /** - * Stores the given content into a file with the given name and content type using the given metadata. - * - * @param content must not be {@literal null}. - * @param filename must not be {@literal null} or empty. - * @param contentType can be {@literal null}. - * @param metadata can be {@literal null}. - * @return a {@link Mono} emitting the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just - * created. - */ - Mono store(AsyncInputStream content, @Nullable String filename, @Nullable String contentType, - @Nullable Document metadata); - /** * Stores the given content into a file with the given name and content type using the given metadata. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java index 173ab24002..14be071ebf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java @@ -16,20 +16,17 @@ package org.springframework.data.mongodb.gridfs; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.function.IntFunction; - -import org.reactivestreams.Publisher; -import org.springframework.core.io.AbstractResource; import org.springframework.core.io.Resource; import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import com.mongodb.client.gridfs.model.GridFSFile; +import com.mongodb.reactivestreams.client.gridfs.GridFSDownloadPublisher; /** * Reactive {@link GridFSFile} based {@link Resource} implementation. @@ -38,13 +35,10 @@ * @author Christoph Strobl * @since 2.2 */ -public class ReactiveGridFsResource extends AbstractResource { - - private static final Integer DEFAULT_CHUNK_SIZE = 256 * 1024; +public class ReactiveGridFsResource { - private final @Nullable GridFSFile file; + private final GridFSDownloadPublisher content; private final String filename; - private final IntFunction> contentFunction; /** * Creates a new, absent {@link ReactiveGridFsResource}. @@ -52,35 +46,10 @@ public class ReactiveGridFsResource extends AbstractResource { * @param filename filename of the absent resource. * @param content */ - private ReactiveGridFsResource(String filename, Publisher content) { + public ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher content) { - this.file = null; + this.content = content; this.filename = filename; - this.contentFunction = any -> Flux.from(content); - } - - /** - * Creates a new {@link ReactiveGridFsResource} from the given {@link GridFSFile}. - * - * @param file must not be {@literal null}. - * @param content - */ - public ReactiveGridFsResource(GridFSFile file, Publisher content) { - this(file, (IntFunction>) any -> Flux.from(content)); - } - - /** - * Creates a new {@link ReactiveGridFsResource} from the given {@link GridFSFile}. - * - * @param file must not be {@literal null}. - * @param contentFunction - * @since 2.2.1 - */ - ReactiveGridFsResource(GridFSFile file, IntFunction> contentFunction) { - - this.file = file; - this.filename = file.getFilename(); - this.contentFunction = contentFunction; } /** @@ -93,123 +62,54 @@ public ReactiveGridFsResource(GridFSFile file, Publisher content) { public static ReactiveGridFsResource absent(String filename) { Assert.notNull(filename, "Filename must not be null"); - - return new ReactiveGridFsResource(filename, Flux.empty()); + return new ReactiveGridFsResource(filename, null); } - /* - * (non-Javadoc) - * @see org.springframework.core.io.InputStreamResource#getInputStream() - */ - @Override - public InputStream getInputStream() throws IllegalStateException { - throw new UnsupportedOperationException(); - } - - /* - * (non-Javadoc) - * @see org.springframework.core.io.AbstractResource#contentLength() - */ - @Override - public long contentLength() throws IOException { - - verifyExists(); - return getGridFSFile().getLength(); - } - - /* - * (non-Javadoc) + /** * @see org.springframework.core.io.AbstractResource#getFilename() */ - @Override public String getFilename() throws IllegalStateException { return this.filename; } - /* - * (non-Javadoc) - * @see org.springframework.core.io.AbstractResource#exists() - */ - @Override - public boolean exists() { - return this.file != null; - } - - /* - * (non-Javadoc) - * @see org.springframework.core.io.AbstractResource#lastModified() - */ - @Override - public long lastModified() throws IOException { - - verifyExists(); - return getGridFSFile().getUploadDate().getTime(); - } - - /* - * (non-Javadoc) - * @see org.springframework.core.io.AbstractResource#getDescription() - */ - @Override - public String getDescription() { - return String.format("GridFs resource [%s]", this.getFilename()); - } - - /** - * Returns the {@link Resource}'s id. - * - * @return never {@literal null}. - * @throws IllegalStateException if the file does not {@link #exists()}. - */ - public Object getId() { - - Assert.state(exists(), () -> String.format("%s does not exist.", getDescription())); - - return getGridFSFile().getId(); - } - /** * @return the underlying {@link GridFSFile}. Can be {@literal null} if absent. * @since 2.2 */ - @Nullable - public GridFSFile getGridFSFile() { - return file; + public Mono getGridFSFile() { + return content != null ? Mono.from(content.getGridFSFile()) : Mono.empty(); } /** - * Retrieve the download stream using the default chunk size of 256 kB. - * - * @return a {@link Flux} emitting data chunks one by one. Please make sure to - * {@link org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release} all - * {@link DataBuffer buffers} when done. */ public Flux getDownloadStream() { - return getDownloadStream(DEFAULT_CHUNK_SIZE); + + if (content == null) { + return Flux.empty(); + } + + return createDownloadStream(content); } /** - * Retrieve the download stream. - * - * @param chunkSize chunk size in bytes to use. - * @return a {@link Flux} emitting data chunks one by one. Please make sure to - * {@link org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release} all - * {@link DataBuffer buffers} when done. - * @since 2.2.1 */ public Flux getDownloadStream(int chunkSize) { - if (!exists()) { - return Flux.error(new FileNotFoundException(String.format("%s does not exist.", getDescription()))); + if (content == null) { + return Flux.empty(); + } - return contentFunction.apply(chunkSize); + return createDownloadStream(content.bufferSizeBytes(chunkSize)); } - private void verifyExists() throws FileNotFoundException { + private Flux createDownloadStream(GridFSDownloadPublisher publisher) { - if (!exists()) { - throw new FileNotFoundException(String.format("%s does not exist.", getDescription())); - } + DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); + return Flux.from(publisher).map(bufferFactory::wrap); + } + + public boolean exists() { + return content != null; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index 3537b146ed..c7f3c8f31d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -21,6 +21,8 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.nio.ByteBuffer; + import org.bson.Document; import org.bson.types.ObjectId; import org.reactivestreams.Publisher; @@ -37,12 +39,12 @@ import org.springframework.util.StringUtils; import com.mongodb.client.gridfs.model.GridFSFile; +import com.mongodb.client.gridfs.model.GridFSUploadOptions; import com.mongodb.reactivestreams.client.MongoDatabase; -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; import com.mongodb.reactivestreams.client.gridfs.GridFSBucket; import com.mongodb.reactivestreams.client.gridfs.GridFSBuckets; -import com.mongodb.reactivestreams.client.gridfs.GridFSDownloadStream; import com.mongodb.reactivestreams.client.gridfs.GridFSFindPublisher; +import com.mongodb.reactivestreams.client.gridfs.GridFSUploadPublisher; /** * {@link ReactiveGridFsOperations} implementation to store content into MongoDB GridFS. Uses by default @@ -51,6 +53,7 @@ * @author Mark Paluch * @author Nick Stolwijk * @author Denis Zavedeev + * @author Christoph Strobl * @since 2.2 */ public class ReactiveGridFsTemplate extends GridFsOperationsSupport implements ReactiveGridFsOperations { @@ -105,16 +108,6 @@ public ReactiveGridFsTemplate(DataBufferFactory dataBufferFactory, ReactiveMongo this.bucket = bucket; } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#store(com.mongodb.reactivestreams.client.gridfs.AsyncInputStream, java.lang.String, java.lang.String, java.lang.Object) - */ - @Override - public Mono store(AsyncInputStream content, @Nullable String filename, @Nullable String contentType, - @Nullable Object metadata) { - return store(content, filename, contentType, toDocument(metadata)); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#store(org.reactivestreams.Publisher, java.lang.String, java.lang.String, java.lang.Object) @@ -125,18 +118,6 @@ public Mono store(Publisher content, @Nullable String file return store(content, filename, contentType, toDocument(metadata)); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#store(com.mongodb.reactivestreams.client.gridfs.AsyncInputStream, java.lang.String, java.lang.String, org.bson.Document) - */ - @Override - public Mono store(AsyncInputStream content, @Nullable String filename, @Nullable String contentType, - @Nullable Document metadata) { - - Assert.notNull(content, "InputStream must not be null!"); - return Mono.from(getGridFs().uploadFromStream(filename, content, computeUploadOptionsFor(contentType, metadata))); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#store(org.reactivestreams.Publisher, java.lang.String, java.lang.String, org.bson.Document) @@ -147,7 +128,12 @@ public Mono store(Publisher content, @Nullable String file Assert.notNull(content, "Content must not be null!"); - return BinaryStreamAdapters.toAsyncInputStream(content).flatMap(it -> store(it, filename, contentType, metadata)); + GridFSUploadOptions uploadOptions = new GridFSUploadOptions(); + uploadOptions.metadata(metadata); + + GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher(filename, + Flux.from(content).map(this::dataBufferToByteBuffer), uploadOptions); + return Mono.from(publisher); } /* @@ -223,12 +209,7 @@ public Mono getResource(GridFSFile file) { Assert.notNull(file, "GridFSFile must not be null!"); return Mono.fromSupplier(() -> { - - return new ReactiveGridFsResource(file, chunkSize -> { - - GridFSDownloadStream stream = getGridFs().openDownloadStream(file.getId()); - return BinaryStreamAdapters.toPublisher(stream, dataBufferFactory, chunkSize); - }); + return new ReactiveGridFsResource(file.getFilename(), getGridFs().downloadToPublisher(file.getId())); }); } @@ -284,4 +265,14 @@ protected GridFSBucket getGridFs() { MongoDatabase db = dbFactory.getMongoDatabase(); return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket); } + + private ByteBuffer dataBufferToByteBuffer(DataBuffer buffer) { + + ByteBuffer byteBuffer = buffer.asByteBuffer(); + ByteBuffer copy = ByteBuffer.allocate(byteBuffer.remaining()); + byteBuffer.put(copy); + copy.flip(); + + return copy; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index ff84452d8a..1eb4f66c31 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -16,9 +16,9 @@ package org.springframework.data.mongodb.repository.query; import org.bson.Document; +import org.bson.codecs.configuration.CodecRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Query; @@ -28,6 +28,9 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Assert; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoDatabase; + /** * Query to use a plain JSON String to create the {@link Query} to actually execute. * @@ -40,11 +43,11 @@ public class StringBasedMongoQuery extends AbstractMongoQuery { private static final String COUNT_EXISTS_AND_DELETE = "Manually defined query for %s cannot be a count and exists or delete query at the same time!"; private static final Logger LOG = LoggerFactory.getLogger(StringBasedMongoQuery.class); - private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); private final String query; private final String fieldSpec; + private final ParameterBindingDocumentCodec codec; private final SpelExpressionParser expressionParser; private final QueryMethodEvaluationContextProvider evaluationContextProvider; @@ -106,6 +109,10 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati this.isExistsQuery = false; this.isDeleteQuery = false; } + + CodecRegistry codecRegistry = mongoOperations.execute(MongoDatabase::getCodecRegistry); + this.codec = new ParameterBindingDocumentCodec( + codecRegistry != null ? codecRegistry : MongoClientSettings.getDefaultCodecRegistry()); } /* @@ -118,8 +125,8 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, () -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); - Document queryObject = CODEC.decode(this.query, bindingContext); - Document fieldsObject = CODEC.decode(this.fieldSpec, bindingContext); + Document queryObject = codec.decode(this.query, bindingContext); + Document fieldsObject = codec.decode(this.fieldSpec, bindingContext); Query query = new BasicQuery(queryObject, fieldsObject).with(accessor.getSort()); diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd index a6f5ceffd4..e670b66cde 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd @@ -370,6 +370,16 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 + + + + + + + + + + @@ -471,6 +481,16 @@ The application name to use when connecting to MongoDB. Mainly used to identify ]]> + + + + + + + + values = definition.getPropertyValues().getPropertyValueList(); - values.forEach(System.out::println); assertThat(values.get(2).getValue()).isInstanceOf(BeanDefinition.class); BeanDefinition x = (BeanDefinition) values.get(2).getValue(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java index ee93abf13a..98732af8d9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java @@ -17,11 +17,13 @@ import static org.assertj.core.api.Assertions.*; +import org.bson.UuidRepresentation; import org.junit.Test; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.data.mongodb.config.ReadConcernPropertyEditor; import org.springframework.data.mongodb.config.ReadPreferencePropertyEditor; +import org.springframework.data.mongodb.config.UUidRepresentationPropertyEditor; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.ReadConcern; @@ -63,4 +65,19 @@ public void convertsReadConcernConcernCorrectly() { MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); assertThat(ReflectionTestUtils.getField(bean, "readConcern")).isEqualTo(ReadConcern.MAJORITY); } + + @Test // DATAMONGO-2427 + public void convertsUuidRepresentationCorrectly() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); + definition.getPropertyValues().addPropertyValue("uUidRepresentation", "STANDARD"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerCustomEditor(ReadPreference.class, UUidRepresentationPropertyEditor.class); + + factory.registerBeanDefinition("factory", definition); + + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "uUidRepresentation")).isEqualTo(UuidRepresentation.STANDARD); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 4ec1a1bdcb..217a86a42f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -20,6 +20,7 @@ import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.core.query.Update.*; +import com.mongodb.MongoClientSettings; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java deleted file mode 100644 index 86609ca8c1..0000000000 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/BinaryStreamAdaptersUnitTests.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2019-2020 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 - * - * https://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.gridfs; - -import static org.assertj.core.api.Assertions.*; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import org.junit.Test; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; -import org.springframework.util.StreamUtils; - -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; -import com.mongodb.reactivestreams.client.gridfs.helpers.AsyncStreamHelper; - -/** - * Unit tests for {@link BinaryStreamAdapters}. - * - * @author Mark Paluch - */ -public class BinaryStreamAdaptersUnitTests { - - @Test // DATAMONGO-1855 - public void shouldAdaptAsyncInputStreamToDataBufferPublisher() throws IOException { - - ClassPathResource resource = new ClassPathResource("gridfs/gridfs.xml"); - - byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); - AsyncInputStream inputStream = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - - Flux dataBuffers = BinaryStreamAdapters.toPublisher(inputStream, new DefaultDataBufferFactory(), 256); - - DataBufferUtils.join(dataBuffers) // - .as(StepVerifier::create) // - .consumeNextWith(actual -> { - - byte[] actualContent = new byte[actual.readableByteCount()]; - actual.read(actualContent); - assertThat(actualContent).isEqualTo(content); - }) // - .verifyComplete(); - } - - @Test // DATAMONGO-1855 - public void shouldAdaptBinaryPublisherToAsyncInputStream() throws IOException { - - ClassPathResource resource = new ClassPathResource("gridfs/gridfs.xml"); - - byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); - - Flux dataBuffers = DataBufferUtils.readInputStream(resource::getInputStream, - new DefaultDataBufferFactory(), 10); - - AsyncInputStream inputStream = BinaryStreamAdapters.toAsyncInputStream(dataBuffers).block(); - ByteBuffer complete = readBuffer(inputStream); - - assertThat(complete).isEqualTo(ByteBuffer.wrap(content)); - } - - static ByteBuffer readBuffer(AsyncInputStream inputStream) { - - ByteBuffer complete = ByteBuffer.allocate(1024); - - boolean hasData = true; - while (hasData) { - - ByteBuffer chunk = ByteBuffer.allocate(100); - - Integer bytesRead = Mono.from(inputStream.read(chunk)).block(); - - chunk.flip(); - complete.put(chunk); - - hasData = bytesRead > -1; - } - - complete.flip(); - - return complete; - } -} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java deleted file mode 100644 index e1336364f3..0000000000 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapterUnitTests.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019-2020 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 - * - * https://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.gridfs; - -import static org.mockito.Mockito.*; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import org.junit.Test; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; - -/** - * Unit tests for {@link DataBufferPublisherAdapter}. - * - * @author Mark Paluch - */ -public class DataBufferPublisherAdapterUnitTests { - - DataBufferFactory factory = new DefaultDataBufferFactory(); - - @Test // DATAMONGO-2230 - public void adapterShouldPropagateErrors() { - - AsyncInputStreamAdapter asyncInput = mock(AsyncInputStreamAdapter.class); - - when(asyncInput.read(any())).thenReturn(Mono.just(1), Mono.error(new IllegalStateException())); - when(asyncInput.close()).thenReturn(Mono.empty()); - - Flux binaryStream = DataBufferPublisherAdapter.createBinaryStream(asyncInput, factory, 256); - - StepVerifier.create(binaryStream, 0) // - .thenRequest(1) // - .expectNextCount(1) // - .thenRequest(1) // - .verifyError(IllegalStateException.class); - } -} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index a444b99b52..b3d0e39830 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -26,13 +26,16 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Arrays; import org.bson.BsonObjectId; import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -54,8 +57,11 @@ import com.mongodb.client.gridfs.model.GridFSFile; import com.mongodb.internal.HexUtils; -import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; -import com.mongodb.reactivestreams.client.gridfs.helpers.AsyncStreamHelper; +import com.mongodb.internal.connection.tlschannel.impl.ByteBufferUtil; +import com.mongodb.reactivestreams.client.gridfs.GridFSBucket; +import com.mongodb.reactivestreams.client.gridfs.GridFSBuckets; +import com.mongodb.reactivestreams.client.gridfs.GridFSUploadPublisher; +import com.mongodb.reactivestreams.client.internal.Publishers; /** * Integration tests for {@link ReactiveGridFsTemplate}. @@ -85,6 +91,7 @@ public void setUp() { } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void storesAndFindsSimpleDocument() { DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); @@ -102,6 +109,7 @@ public void storesAndFindsSimpleDocument() { } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void storesAndLoadsLargeFileCorrectly() { ByteBuffer buffer = ByteBuffer.allocate(1000 * 1000); // 1 mb @@ -160,13 +168,15 @@ public void storesAndLoadsLargeFileCorrectly() { // } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void writesMetadataCorrectly() throws IOException { Document metadata = new Document("key", "value"); - AsyncInputStream stream = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); + Flux source = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); + // AsyncInputStream stream = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - ObjectId reference = operations.store(stream, "foo.xml", "binary/octet-stream", metadata).block(); + ObjectId reference = operations.store(source, "foo.xml", "binary/octet-stream", metadata).block(); operations.find(query(whereMetaData("key").is("value"))) // .as(StepVerifier::create) // @@ -177,14 +187,14 @@ public void writesMetadataCorrectly() throws IOException { } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void marshalsComplexMetadata() throws IOException { Metadata metadata = new Metadata(); metadata.version = "1.0"; - AsyncInputStream stream = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - - ObjectId reference = operations.store(stream, "foo.xml", "binary/octet-stream", metadata).block(); + Flux source = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); + ObjectId reference = operations.store(source, "foo.xml", "binary/octet-stream", metadata).block(); operations.find(query(whereMetaData("version").is("1.0"))) // .as(StepVerifier::create) // @@ -196,12 +206,12 @@ public void marshalsComplexMetadata() throws IOException { } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void getResourceShouldRetrieveContentByIdentity() throws IOException { byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); - AsyncInputStream upload = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - - ObjectId reference = operations.store(upload, "foo.xml", null, null).block(); + Flux source = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); + ObjectId reference = operations.store(source, "foo.xml", null, null).block(); operations.findOne(query(where("_id").is(reference))).flatMap(operations::getResource) .flatMapMany(ReactiveGridFsResource::getDownloadStream) // @@ -218,11 +228,12 @@ public void getResourceShouldRetrieveContentByIdentity() throws IOException { } @Test // DATAMONGO-1855, DATAMONGO-2240 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void shouldEmitFirstEntryWhenFindFirstRetrievesMoreThanOneResult() throws IOException { - AsyncInputStream upload1 = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - AsyncInputStream upload2 = AsyncStreamHelper - .toAsyncInputStream(new ClassPathResource("gridfs/another-resource.xml").getInputStream()); + Flux upload1 = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); + Flux upload2 = DataBufferUtils.read(new ClassPathResource("gridfs/another-resource.xml"), + new DefaultDataBufferFactory(), 256); operations.store(upload1, "foo.xml", null, null).block(); operations.store(upload2, "foo2.xml", null, null).block(); @@ -244,16 +255,17 @@ public void shouldReturnNoGridFsFileWhenAbsent() { .assertNext(actual -> { assertThat(actual.exists()).isFalse(); - assertThat(actual.getGridFSFile()).isNull(); + assertThat(actual.getGridFSFile()).isEqualTo(Mono.empty()); }).verifyComplete(); } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void shouldEmitErrorWhenFindOneRetrievesMoreThanOneResult() throws IOException { - AsyncInputStream upload1 = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - AsyncInputStream upload2 = AsyncStreamHelper - .toAsyncInputStream(new ClassPathResource("gridfs/another-resource.xml").getInputStream()); + Flux upload1 = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); + Flux upload2 = DataBufferUtils.read(new ClassPathResource("gridfs/another-resource.xml"), + new DefaultDataBufferFactory(), 256); operations.store(upload1, "foo.xml", null, null).block(); operations.store(upload2, "foo2.xml", null, null).block(); @@ -265,10 +277,11 @@ public void shouldEmitErrorWhenFindOneRetrievesMoreThanOneResult() throws IOExce } @Test // DATAMONGO-1855 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void getResourcesByPattern() throws IOException { byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); - AsyncInputStream upload = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); + Flux upload = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); operations.store(upload, "foo.xml", null, null).block(); @@ -287,6 +300,7 @@ public void getResourcesByPattern() throws IOException { } @Test // DATAMONGO-765 + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void considersSkipLimitWhenQueryingFiles() { DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); @@ -311,4 +325,57 @@ public void considersSkipLimitWhenQueryingFiles() { static class Metadata { String version; } + + @Test // + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") + public void xxx() { + + GridFSBucket buckets = GridFSBuckets.create(dbFactory.getMongoDatabase()); + + DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); + DefaultDataBuffer first = factory.wrap("first".getBytes()); + // DefaultDataBuffer second = factory.wrap("second".getBytes()); + + Flux source = Flux.just(first); + + // GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", + // Mono.just(ByteBuffer.wrap("hello".getBytes()))); + GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", + source.map(DataBuffer::asByteBuffer)); + Mono idPublisher = Mono.from(objectIdGridFSUploadPublisher); + idPublisher.as(StepVerifier::create).expectNextCount(1).verifyComplete(); + } + + @Test + @Ignore("https://jira.mongodb.org/browse/JAVARS-224") + public void xxx2() { + + GridFSBucket buckets = GridFSBuckets.create(dbFactory.getMongoDatabase()); + + Flux source = Flux.just(ByteBuffer.wrap("first".getBytes()), ByteBuffer.wrap("second".getBytes())); + Publisher rawSource = toPublisher(ByteBuffer.wrap("first".getBytes()), + ByteBuffer.wrap("second".getBytes())); + + // GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", + // Mono.just(ByteBuffer.wrap("hello".getBytes()))); + // GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", source); + GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", rawSource); + Mono.from(objectIdGridFSUploadPublisher).as(StepVerifier::create).expectNextCount(1).verifyComplete(); + + // idPublisher; + } + + private static Publisher toPublisher(final ByteBuffer... byteBuffers) { + return Publishers.publishAndFlatten(callback -> callback.onResult(Arrays.asList(byteBuffers), null)); + } + + private ByteBuffer hack(DataBuffer buffer) { + + ByteBuffer byteBuffer = buffer.asByteBuffer(); + ByteBuffer copy = ByteBuffer.allocate(byteBuffer.remaining()); + ByteBufferUtil.copy(byteBuffer, copy, byteBuffer.arrayOffset()); + copy.flip(); + + return copy; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 4261c56a1f..3a8a31ac8f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -30,13 +30,15 @@ import org.bson.BsonBinarySubType; import org.bson.Document; +import org.bson.UuidRepresentation; +import org.bson.codecs.configuration.CodecRegistry; import org.bson.types.ObjectId; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.data.mongodb.core.DbCallback; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.MongoOperations; @@ -57,6 +59,9 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Base64Utils; +import com.mongodb.MongoClientSettings; +import com.mongodb.reactivestreams.client.MongoClients; + /** * Unit tests for {@link StringBasedMongoQuery}. * @@ -350,7 +355,18 @@ public void shouldSupportNonQuotedUUIDReplacement() { org.springframework.data.mongodb.core.query.Query reference = new BasicQuery( "{'lastname' : { $binary:\"5PHq4zvkTYa5WbZAgvtjNg==\", $type: \"03\"}}"); - assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); + // CodecRegistry registry = + // MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.JAVA_LEGACY).build().getCodecRegistry(); + + // TODO: use OverridableUuidRepresentationCodecRegistry instead to save resources + CodecRegistry registry = MongoClients + .create(MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.JAVA_LEGACY).build()) + .getDatabase("database").getCodecRegistry(); + + // OverridableUuidRepresentationCodecRegistry + + assertThat(query.getQueryObject().toJson(registry.get(Document.class))) + .isEqualTo(reference.getQueryObject().toJson()); } @Test // DATAMONGO-2029 @@ -367,7 +383,36 @@ public void shouldSupportNonQuotedUUIDCollectionReplacement() { org.springframework.data.mongodb.core.query.Query reference = new BasicQuery( "{'lastname' : { $in: [{ $binary : \"5PHq4zvkTYa5WbZAgvtjNg==\", $type : \"03\" }, { $binary : \"5PH+yjvkTYa5WbZAgvtjNg==\", $type : \"03\" }]}}"); - assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); + // TODO: use OverridableUuidRepresentationCodecRegistry instead to save resources + CodecRegistry registry = MongoClients + .create(MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.JAVA_LEGACY).build()) + .getDatabase("database").getCodecRegistry(); + assertThat(query.getQueryObject().toJson(registry.get(Document.class))) + .isEqualTo(reference.getQueryObject().toJson()); + } + + @Test // DATAMONGO-2427 + public void shouldSupportNonQuotedUUIDCollectionReplacementWhenUsingNonLegacyUUIDCodec() { + + // TODO: use OverridableUuidRepresentationCodecRegistry instead to save resources + CodecRegistry registry = MongoClients + .create(MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.STANDARD).build()) + .getDatabase("database").getCodecRegistry(); + when(operations.execute(any(DbCallback.class))).thenReturn(registry); + + UUID uuid1 = UUID.fromString("864de43b-e3ea-f1e4-3663-fb8240b659b9"); + UUID uuid2 = UUID.fromString("864de43b-cafe-f1e4-3663-fb8240b659b9"); + + ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, + (Object) Arrays.asList(uuid1, uuid2)); + StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAsUUIDIn", List.class); + + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); + org.springframework.data.mongodb.core.query.Query reference = new BasicQuery( + "{'lastname' : { $in: [{ $binary : \"hk3kO+Pq8eQ2Y/uCQLZZuQ==\", $type : \"04\" }, { $binary : \"hk3kO8r+8eQ2Y/uCQLZZuQ==\", $type : \"04\" }]}}"); + + assertThat(query.getQueryObject().toJson(registry.get(Document.class))) + .isEqualTo(reference.getQueryObject().toJson()); } @Test // DATAMONGO-1911 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 3924b50abd..7bb71cff8b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -22,8 +22,10 @@ import java.util.List; import org.bson.Document; +import org.springframework.data.mongodb.SpringDataMongoDB; import org.springframework.data.util.Version; +import com.mongodb.ConnectionString; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; @@ -55,7 +57,9 @@ public static MongoClient client() { } public static MongoClient client(String host, int port) { - return com.mongodb.client.MongoClients.create(String.format(CONNECTION_STRING_PATTERN, host, port)); + + ConnectionString connectionString = new ConnectionString(String.format(CONNECTION_STRING_PATTERN, host, port)); + return com.mongodb.client.MongoClients.create(connectionString, SpringDataMongoDB.driverInformation()); } /** @@ -68,7 +72,9 @@ public static com.mongodb.reactivestreams.client.MongoClient reactiveClient() { } public static com.mongodb.reactivestreams.client.MongoClient reactiveClient(String host, int port) { - return MongoClients.create(String.format(CONNECTION_STRING_PATTERN, host, port)); + + ConnectionString connectionString = new ConnectionString(String.format(CONNECTION_STRING_PATTERN, host, port)); + return MongoClients.create(connectionString, SpringDataMongoDB.driverInformation()); } /** diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml index 912d318ba1..1bd3aa2a05 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml @@ -37,4 +37,8 @@ connection-pool-max-connection-idle-time="30" connection-pool-max-wait-time="15" /> + + + + diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index 5077901320..5de900855e 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -13,6 +13,9 @@ Instead of the single artifact uber-jar `mongo-java-driver`, imports are now spl * `org.mongodb:mongodb-driver-sync` (optional) * `org.mongodb:mongodb-driver-reactivestreams` (optional) +Depending on the application one of the `mongodb-driver-sync`, `mongodb-driver-reactivestreams` artifacts is is required next to the mandatory `mongodb-driver-core`. +It is possible to combine the sync and reactive drivers in one application if needed. + == Java Configuration .Java API changes @@ -140,3 +143,26 @@ Element | Comment |=== +== Other Changes + +=== UUID Types + +The MongoDB UUID representation can now be configured with different formats. +This has to be done via `MongoClientSettings` as shown in the snippet below. + +.UUid Codec Configuration +==== +[source,java] +---- + +static class Config extends AbstractMongoClientConfiguration { + + @Override + public void configureClientSettings(MongoClientSettings.Builder builder) { + builder.uuidRepresentation(UuidRepresentation.STANDARD); + } + + // ... +} +---- +==== From f688cca40057b746bc3860b3da23d7c3875b009d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 13 Dec 2019 11:40:20 +0100 Subject: [PATCH 0048/1381] DATAMONGO-2427 - Switch to MongoDB Driver 4.0.0-beta1. Enable disabled tests. Adapt to ReactiveGridFS changes. Use WriteConcern.MAJORITY in tests. Original pull request: #823. --- .travis.yml | 8 +- Jenkinsfile | 168 ++---------------- ci/openjdk11-mongodb-4.0/Dockerfile | 14 -- ci/openjdk11-mongodb-4.1/Dockerfile | 14 -- ci/openjdk11-mongodb-4.2/Dockerfile | 2 +- ci/openjdk13-mongodb-4.0/Dockerfile | 14 -- ci/openjdk13-mongodb-4.1/Dockerfile | 14 -- ci/openjdk13-mongodb-4.2/Dockerfile | 2 +- ci/openjdk8-mongodb-4.0/Dockerfile | 4 +- ci/openjdk8-mongodb-4.1/Dockerfile | 14 -- ci/openjdk8-mongodb-4.2/Dockerfile | 2 +- ci/openjdk8-mongodb-4.3/Dockerfile | 14 ++ pom.xml | 2 +- .../mongodb/core/ReactiveMongoTemplate.java | 5 +- .../gridfs/ReactiveGridFsResource.java | 88 +++++++-- .../gridfs/ReactiveGridFsTemplate.java | 14 +- .../ReactiveTransactionIntegrationTests.java | 1 - .../core/MongoTemplateUpdateTests.java | 4 +- .../ReactiveMongoTemplateUpdateTests.java | 3 +- .../ReactiveGridFsResourceUnitTests.java | 97 ++++++++++ .../gridfs/ReactiveGridFsTemplateTests.java | 92 +--------- .../mongodb/test/util/MongoTestUtils.java | 4 +- 22 files changed, 230 insertions(+), 350 deletions(-) delete mode 100644 ci/openjdk11-mongodb-4.0/Dockerfile delete mode 100644 ci/openjdk11-mongodb-4.1/Dockerfile delete mode 100644 ci/openjdk13-mongodb-4.0/Dockerfile delete mode 100644 ci/openjdk13-mongodb-4.1/Dockerfile delete mode 100644 ci/openjdk8-mongodb-4.1/Dockerfile create mode 100644 ci/openjdk8-mongodb-4.3/Dockerfile create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java diff --git a/.travis.yml b/.travis.yml index 653e62a688..f03d5f2837 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,10 +21,10 @@ matrix: env: matrix: - - MONGO_VERSION=4.1.10 - - MONGO_VERSION=4.0.4 - - MONGO_VERSION=3.6.12 - - MONGO_VERSION=3.4.20 + - MONGO_VERSION=4.2.2 + - MONGO_VERSION=4.0.14 + - MONGO_VERSION=3.6.16 + - MONGO_VERSION=3.4.23 global: - PROFILE=ci diff --git a/Jenkinsfile b/Jenkinsfile index c4cb5fb440..d2e6804c50 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,64 +30,32 @@ pipeline { } } } - stage('Publish JDK 8 + MongoDB 4.1') { - when { - changeset "ci/openjdk8-mongodb-4.1/**" - } - agent { label 'data' } - options { timeout(time: 30, unit: 'MINUTES') } - - steps { - script { - def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.1", "ci/openjdk8-mongodb-4.1/") - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - image.push() - } - } - } - } stage('Publish JDK 8 + MongoDB 4.2') { - when { - changeset "ci/openjdk8-mongodb-4.2/**" - } - agent { label 'data' } - options { timeout(time: 30, unit: 'MINUTES') } - - steps { - script { - def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.2", "ci/openjdk8-mongodb-4.2/") - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - image.push() - } - } - } - } - stage('Publish JDK 11 + MongoDB 4.0') { when { - changeset "ci/openjdk11-mongodb-4.0/**" + changeset "ci/openjdk8-mongodb-4.2/**" } agent { label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { script { - def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.0", "ci/openjdk11-mongodb-4.0/") + def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.2", "ci/openjdk8-mongodb-4.2/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } } } } - stage('Publish JDK 11 + MongoDB 4.1') { + stage('Publish JDK 8 + MongoDB 4.3') { when { - changeset "ci/openjdk11-mongodb-4.1/**" + changeset "ci/openjdk8-mongodb-4.3/**" } agent { label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { script { - def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.1", "ci/openjdk11-mongodb-4.1/") + def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.3", "ci/openjdk8-mongodb-4.3/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } @@ -110,38 +78,6 @@ pipeline { } } } - stage('Publish JDK 13 + MongoDB 4.0') { - when { - changeset "ci/openjdk13-mongodb-4.0/**" - } - agent { label 'data' } - options { timeout(time: 30, unit: 'MINUTES') } - - steps { - script { - def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.0", "ci/openjdk13-mongodb-4.0/") - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - image.push() - } - } - } - } - stage('Publish JDK 13 + MongoDB 4.1') { - when { - changeset "ci/openjdk13-mongodb-4.1/**" - } - agent { label 'data' } - options { timeout(time: 30, unit: 'MINUTES') } - - steps { - script { - def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.1", "ci/openjdk13-mongodb-4.1/") - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - image.push() - } - } - } - } stage('Publish JDK 13 + MongoDB 4.2') { when { changeset "ci/openjdk13-mongodb-4.2/**" @@ -170,7 +106,7 @@ pipeline { } agent { docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.2:latest' + image 'springci/spring-data-openjdk8-with-mongodb-4.3:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } @@ -195,46 +131,6 @@ pipeline { } } parallel { - stage("test: baseline (jdk11)") { - agent { - docker { - image 'springci/spring-data-openjdk11-with-mongodb-4.2:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } - } - options { timeout(time: 30, unit: 'MINUTES') } - steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' - } - } - - stage("test: baseline (jdk13)") { - agent { - docker { - image 'springci/spring-data-openjdk13-with-mongodb-4.2:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } - } - options { timeout(time: 30, unit: 'MINUTES') } - steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' - } - } - stage("test: mongodb 4.0 (jdk8)") { agent { docker { @@ -255,50 +151,10 @@ pipeline { } } - stage("test: mongodb 4.0 (jdk11)") { - agent { - docker { - image 'springci/spring-data-openjdk11-with-mongodb-4.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } - } - options { timeout(time: 30, unit: 'MINUTES') } - steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' - } - } - - stage("test: mongodb 4.0 (jdk13)") { - agent { - docker { - image 'springci/spring-data-openjdk13-with-mongodb-4.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } - } - options { timeout(time: 30, unit: 'MINUTES') } - steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' - } - } - - stage("test: mongodb 4.1 (jdk8)") { + stage("test: mongodb 4.2 (jdk8)") { agent { docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.1:latest' + image 'springci/spring-data-openjdk8-with-mongodb-4.2:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } @@ -315,10 +171,10 @@ pipeline { } } - stage("test: mongodb 4.1 (jdk11)") { + stage("test: baseline (jdk11)") { agent { docker { - image 'springci/spring-data-openjdk11-with-mongodb-4.1:latest' + image 'springci/spring-data-openjdk11-with-mongodb-4.2:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } @@ -335,10 +191,10 @@ pipeline { } } - stage("test: mongodb 4.1 (jdk13)") { + stage("test: baseline (jdk13)") { agent { docker { - image 'springci/spring-data-openjdk13-with-mongodb-4.1:latest' + image 'springci/spring-data-openjdk13-with-mongodb-4.2:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } diff --git a/ci/openjdk11-mongodb-4.0/Dockerfile b/ci/openjdk11-mongodb-4.0/Dockerfile deleted file mode 100644 index 8c450a54f5..0000000000 --- a/ci/openjdk11-mongodb-4.0/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM adoptopenjdk/openjdk11:latest - -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.0.9 mongodb-org-server=4.0.9 mongodb-org-shell=4.0.9 mongodb-org-mongos=4.0.9 mongodb-org-tools=4.0.9 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk11-mongodb-4.1/Dockerfile b/ci/openjdk11-mongodb-4.1/Dockerfile deleted file mode 100644 index 9e9fff1f52..0000000000 --- a/ci/openjdk11-mongodb-4.1/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM adoptopenjdk/openjdk11:latest - -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 4B7C549A058F8B6B - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.1 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.1.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org-unstable=4.1.13 mongodb-org-unstable-server=4.1.13 mongodb-org-unstable-shell=4.1.13 mongodb-org-unstable-mongos=4.1.13 mongodb-org-unstable-tools=4.1.13 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk11-mongodb-4.2/Dockerfile b/ci/openjdk11-mongodb-4.2/Dockerfile index 03eeabb62f..79218ba5e0 100644 --- a/ci/openjdk11-mongodb-4.2/Dockerfile +++ b/ci/openjdk11-mongodb-4.2/Dockerfile @@ -8,7 +8,7 @@ RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb- RUN apt-get update -RUN apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 +RUN apt-get install -y mongodb-org=4.2.2 mongodb-org-server=4.2.2 mongodb-org-shell=4.2.2 mongodb-org-mongos=4.2.2 mongodb-org-tools=4.2.2 RUN apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/ci/openjdk13-mongodb-4.0/Dockerfile b/ci/openjdk13-mongodb-4.0/Dockerfile deleted file mode 100644 index 511db028ab..0000000000 --- a/ci/openjdk13-mongodb-4.0/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM adoptopenjdk/openjdk13:latest - -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.0.9 mongodb-org-server=4.0.9 mongodb-org-shell=4.0.9 mongodb-org-mongos=4.0.9 mongodb-org-tools=4.0.9 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk13-mongodb-4.1/Dockerfile b/ci/openjdk13-mongodb-4.1/Dockerfile deleted file mode 100644 index 5f94bb6f2b..0000000000 --- a/ci/openjdk13-mongodb-4.1/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM adoptopenjdk/openjdk13:latest - -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 4B7C549A058F8B6B - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.1 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.1.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org-unstable=4.1.13 mongodb-org-unstable-server=4.1.13 mongodb-org-unstable-shell=4.1.13 mongodb-org-unstable-mongos=4.1.13 mongodb-org-unstable-tools=4.1.13 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk13-mongodb-4.2/Dockerfile b/ci/openjdk13-mongodb-4.2/Dockerfile index 3f73cd4426..09221a8cab 100644 --- a/ci/openjdk13-mongodb-4.2/Dockerfile +++ b/ci/openjdk13-mongodb-4.2/Dockerfile @@ -8,7 +8,7 @@ RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb- RUN apt-get update -RUN apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 +RUN apt-get install -y mongodb-org=4.2.2 mongodb-org-server=4.2.2 mongodb-org-shell=4.2.2 mongodb-org-mongos=4.2.2 mongodb-org-tools=4.2.2 RUN apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/ci/openjdk8-mongodb-4.0/Dockerfile b/ci/openjdk8-mongodb-4.0/Dockerfile index 18aec0387f..8c2df11650 100644 --- a/ci/openjdk8-mongodb-4.0/Dockerfile +++ b/ci/openjdk8-mongodb-4.0/Dockerfile @@ -8,7 +8,7 @@ RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb- RUN apt-get update -RUN apt-get install -y mongodb-org=4.0.9 mongodb-org-server=4.0.9 mongodb-org-shell=4.0.9 mongodb-org-mongos=4.0.9 mongodb-org-tools=4.0.9 +RUN apt-get install -y mongodb-org=4.0.14 mongodb-org-server=4.0.14 mongodb-org-shell=4.0.14 mongodb-org-mongos=4.0.14 mongodb-org-tools=4.0.14 RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ No newline at end of file + && rm -rf /var/lib/apt/lists/* diff --git a/ci/openjdk8-mongodb-4.1/Dockerfile b/ci/openjdk8-mongodb-4.1/Dockerfile deleted file mode 100644 index 78b1278c18..0000000000 --- a/ci/openjdk8-mongodb-4.1/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM adoptopenjdk/openjdk8:latest - -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 4B7C549A058F8B6B - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.1 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.1.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org-unstable=4.1.13 mongodb-org-unstable-server=4.1.13 mongodb-org-unstable-shell=4.1.13 mongodb-org-unstable-mongos=4.1.13 mongodb-org-unstable-tools=4.1.13 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/ci/openjdk8-mongodb-4.2/Dockerfile b/ci/openjdk8-mongodb-4.2/Dockerfile index 7b32ffb85c..c7e0a4cf84 100644 --- a/ci/openjdk8-mongodb-4.2/Dockerfile +++ b/ci/openjdk8-mongodb-4.2/Dockerfile @@ -8,7 +8,7 @@ RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb- RUN apt-get update -RUN apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 +RUN apt-get install -y mongodb-org=4.2.2 mongodb-org-server=4.2.2 mongodb-org-shell=4.2.2 mongodb-org-mongos=4.2.2 mongodb-org-tools=4.2.2 RUN apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/ci/openjdk8-mongodb-4.3/Dockerfile b/ci/openjdk8-mongodb-4.3/Dockerfile new file mode 100644 index 0000000000..73acfd2f65 --- /dev/null +++ b/ci/openjdk8-mongodb-4.3/Dockerfile @@ -0,0 +1,14 @@ +FROM adoptopenjdk/openjdk8:latest + +RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 + +RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b + +RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/development multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.3.list + +RUN apt-get update + +RUN apt-get install -y mongodb-org=4.3.2 mongodb-org-server=4.3.2 mongodb-org-shell=4.3.2 mongodb-org-mongos=4.3.2 mongodb-org-tools=4.3.2 + +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/pom.xml b/pom.xml index 86fbb52cd2..9db0441fd9 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 4.0.0-SNAPSHOT + 4.0.0-beta1 ${mongo} 1.19 diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 3993105fc6..257839f4a5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -3014,7 +3014,10 @@ private static FindOneAndUpdateOptions convertToFindOneAndUpdateOptions(FindAndM } result = options.getCollation().map(Collation::toMongoCollation).map(result::collation).orElse(result); - result.arrayFilters(arrayFilters); + + if(!CollectionUtils.isEmpty(arrayFilters)) { + result.arrayFilters(arrayFilters); + } return result; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java index 14be071ebf..423226433a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java @@ -18,9 +18,14 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.io.InputStream; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.reactivestreams.Publisher; import org.springframework.core.io.Resource; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -37,19 +42,34 @@ */ public class ReactiveGridFsResource { - private final GridFSDownloadPublisher content; + private final AtomicBoolean consumed = new AtomicBoolean(false); + private final String filename; + private final @Nullable GridFSDownloadPublisher downloadPublisher; + private final DataBufferFactory dataBufferFactory; /** * Creates a new, absent {@link ReactiveGridFsResource}. * * @param filename filename of the absent resource. - * @param content + * @param downloadPublisher */ - public ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher content) { + public ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher downloadPublisher) { + this(filename, downloadPublisher, new DefaultDataBufferFactory()); + } + + /** + * Creates a new, absent {@link ReactiveGridFsResource}. + * + * @param filename filename of the absent resource. + * @param downloadPublisher + */ + ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher downloadPublisher, + DataBufferFactory dataBufferFactory) { - this.content = content; this.filename = filename; + this.downloadPublisher = downloadPublisher; + this.dataBufferFactory = dataBufferFactory; } /** @@ -77,39 +97,81 @@ public String getFilename() throws IllegalStateException { * @since 2.2 */ public Mono getGridFSFile() { - return content != null ? Mono.from(content.getGridFSFile()) : Mono.empty(); + return downloadPublisher != null ? Mono.from(downloadPublisher.getGridFSFile()) : Mono.empty(); + } + + /** + * Obtain the data as {@link InputStream}.
      + * NOTE Buffers data in memory. Use {@link #getDownloadStream()} for large files. + * + * @throws IllegalStateException if the underlying {@link Publisher} has already been consumed. + * @see org.springframework.core.io.InputStreamResource#getInputStream() + * @see #getDownloadStream() + * @see DataBufferUtils#join(Publisher) + * @since 3.0 + */ + public Mono getInputStream() throws IllegalStateException { + + return getDownloadStream() // + .transform(DataBufferUtils::join) // + .as(Mono::from) // + .map(DataBuffer::asInputStream); } /** + * Obtain the download stream emitting chunks of data as they come in.
      + * + * @return {@link Flux#empty()} if the file does not exist. + * @throws IllegalStateException if the underlying {@link Publisher} has already been consumed. + * @see org.springframework.core.io.InputStreamResource#getInputStream() + * @see #getDownloadStream() + * @see DataBufferUtils#join(Publisher) + * @since 3.0 */ public Flux getDownloadStream() { - if (content == null) { + if (downloadPublisher == null) { return Flux.empty(); } - return createDownloadStream(content); + return createDownloadStream(downloadPublisher); } /** + * Obtain the download stream emitting chunks of data with given {@code chunkSize} as they come in. + * + * @param chunkSize the preferred number of bytes per emitted {@link DataBuffer}. + * @return {@link Flux#empty()} if the file does not exist. + * @throws IllegalStateException if the underlying {@link Publisher} has already been consumed. + * @see org.springframework.core.io.InputStreamResource#getInputStream() + * @see #getDownloadStream() + * @see DataBufferUtils#join(Publisher) + * @since 3.0 */ public Flux getDownloadStream(int chunkSize) { - if (content == null) { + if (downloadPublisher == null) { return Flux.empty(); - } - return createDownloadStream(content.bufferSizeBytes(chunkSize)); + return createDownloadStream(downloadPublisher.bufferSizeBytes(chunkSize)); } private Flux createDownloadStream(GridFSDownloadPublisher publisher) { - DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); - return Flux.from(publisher).map(bufferFactory::wrap); + return Flux.from(publisher) // + .map(dataBufferFactory::wrap) // + .doOnSubscribe(it -> this.verifyStreamStillAvailable()); } public boolean exists() { - return content != null; + return downloadPublisher != null; + } + + private void verifyStreamStillAvailable() { + + if (!consumed.compareAndSet(false, true)) { + throw new IllegalStateException("Stream already consumed."); + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index c7f3c8f31d..f6867fb74b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -132,7 +132,7 @@ public Mono store(Publisher content, @Nullable String file uploadOptions.metadata(metadata); GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher(filename, - Flux.from(content).map(this::dataBufferToByteBuffer), uploadOptions); + Flux.from(content).map(DataBuffer::asByteBuffer), uploadOptions); return Mono.from(publisher); } @@ -209,7 +209,7 @@ public Mono getResource(GridFSFile file) { Assert.notNull(file, "GridFSFile must not be null!"); return Mono.fromSupplier(() -> { - return new ReactiveGridFsResource(file.getFilename(), getGridFs().downloadToPublisher(file.getId())); + return new ReactiveGridFsResource(file.getFilename(), getGridFs().downloadToPublisher(file.getId()), dataBufferFactory); }); } @@ -265,14 +265,4 @@ protected GridFSBucket getGridFs() { MongoDatabase db = dbFactory.getMongoDatabase(); return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket); } - - private ByteBuffer dataBufferToByteBuffer(DataBuffer buffer) { - - ByteBuffer byteBuffer = buffer.asByteBuffer(); - ByteBuffer copy = ByteBuffer.allocate(byteBuffer.remaining()); - byteBuffer.put(copy); - copy.flip(); - - return copy; - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index 763d0e148c..de61724af0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -50,7 +50,6 @@ import org.springframework.transaction.support.DefaultTransactionDefinition; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * Integration tests for reactive transaction management. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index d519b9d892..1bbc4d464d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.List; +import lombok.EqualsAndHashCode; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -257,7 +258,7 @@ void aggregateUpdateFirstMatch() { } @Test // DATAMONGO-2331 - @Disabled("https://jira.mongodb.org/browse/JAVA-3432") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") void findAndModifyAppliesAggregationUpdateCorrectly() { Book one = new Book(); @@ -336,6 +337,7 @@ public Versioned(String id, String value) { } } + @EqualsAndHashCode static class Book { @Id Integer id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java index 9d9b280b46..d3fbc3b7a6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.*; +import lombok.EqualsAndHashCode; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; @@ -240,7 +241,6 @@ public void aggregateUpdateFirstMatch() { } @Test // DATAMONGO-2331 - @Disabled("https://jira.mongodb.org/browse/JAVA-3432") public void findAndModifyAppliesAggregationUpdateCorrectly() { Book one = new Book(); @@ -310,6 +310,7 @@ public Versioned(String id, String value) { } } + @EqualsAndHashCode static class Book { @Id Integer id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java new file mode 100644 index 0000000000..c5a8dcb140 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2020 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 + * + * https://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.gridfs; + +import static org.assertj.core.api.Assertions.*; + +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.nio.ByteBuffer; + +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +import com.mongodb.client.gridfs.model.GridFSFile; +import com.mongodb.reactivestreams.client.gridfs.GridFSDownloadPublisher; + +/** + * @author Christoph Strobl + */ +class ReactiveGridFsResourceUnitTests { + + @Test // DATAMONGO-2427 + void streamCanOnlyBeConsumedOnce() { + + ReactiveGridFsResource resource = new ReactiveGridFsResource("file.name", new StubGridFSDownloadPublisher()); + + assertThat(resource.exists()).isTrue(); + + resource.getInputStream().as(StepVerifier::create).verifyComplete(); + resource.getInputStream().as(StepVerifier::create).verifyError(IllegalStateException.class); + resource.getDownloadStream().as(StepVerifier::create).verifyError(IllegalStateException.class); + } + + @Test // DATAMONGO-2427 + void existReturnsFalseForNullPublisher() { + + ReactiveGridFsResource resource = new ReactiveGridFsResource("file.name", null); + + assertThat(resource.exists()).isFalse(); + } + + @Test // DATAMONGO-2427 + void nonExistingResourceProducesEmptyDownloadStream() { + + ReactiveGridFsResource resource = new ReactiveGridFsResource("file.name", null); + + resource.getInputStream().as(StepVerifier::create).verifyComplete(); + resource.getInputStream().as(StepVerifier::create).verifyComplete(); + resource.getDownloadStream().as(StepVerifier::create).verifyComplete(); + } + + private static class StubGridFSDownloadPublisher implements GridFSDownloadPublisher { + + @Override + public Publisher getGridFSFile() { + return Mono.empty(); + } + + @Override + public GridFSDownloadPublisher bufferSizeBytes(int bufferSizeBytes) { + return null; + } + + @Override + public void subscribe(Subscriber s) { + + s.onSubscribe(new Subscription() { + @Override + public void request(long n) { + s.onComplete(); + } + + @Override + public void cancel() { + + } + }); + + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index b3d0e39830..61cfad7a2a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -25,6 +25,7 @@ import reactor.test.StepVerifier; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.util.Arrays; @@ -32,7 +33,6 @@ import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.reactivestreams.Publisher; @@ -53,14 +53,11 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.FileCopyUtils; import org.springframework.util.StreamUtils; import com.mongodb.client.gridfs.model.GridFSFile; import com.mongodb.internal.HexUtils; -import com.mongodb.internal.connection.tlschannel.impl.ByteBufferUtil; -import com.mongodb.reactivestreams.client.gridfs.GridFSBucket; -import com.mongodb.reactivestreams.client.gridfs.GridFSBuckets; -import com.mongodb.reactivestreams.client.gridfs.GridFSUploadPublisher; import com.mongodb.reactivestreams.client.internal.Publishers; /** @@ -91,7 +88,6 @@ public void setUp() { } @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void storesAndFindsSimpleDocument() { DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); @@ -109,7 +105,6 @@ public void storesAndFindsSimpleDocument() { } @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void storesAndLoadsLargeFileCorrectly() { ByteBuffer buffer = ByteBuffer.allocate(1000 * 1000); // 1 mb @@ -148,34 +143,12 @@ public void storesAndLoadsLargeFileCorrectly() { }).verifyComplete(); } - // @Test // DATAMONGO-2392 - // public void storesAndFindsByUUID() throws IOException { - // - // UUID uuid = UUID.randomUUID(); - // - // GridFS fs = new GridFS(mongoClient.getLegacyDb()); - // GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); - // - // in.put("_id", uuid); - // in.put("contentType", "application/octet-stream"); - // in.save(); - // - // operations.findOne(query(where("_id").is(uuid))).flatMap(operations::getResource) - // .flatMapMany(ReactiveGridFsResource::getDownloadStream) // - // .transform(DataBufferUtils::join) // - // .doOnNext(DataBufferUtils::release).as(StepVerifier::create) // - // .expectNextCount(1).verifyComplete(); - // } - @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void writesMetadataCorrectly() throws IOException { Document metadata = new Document("key", "value"); Flux source = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); - // AsyncInputStream stream = AsyncStreamHelper.toAsyncInputStream(resource.getInputStream()); - ObjectId reference = operations.store(source, "foo.xml", "binary/octet-stream", metadata).block(); operations.find(query(whereMetaData("key").is("value"))) // @@ -187,8 +160,7 @@ public void writesMetadataCorrectly() throws IOException { } @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") - public void marshalsComplexMetadata() throws IOException { + public void marshalsComplexMetadata() { Metadata metadata = new Metadata(); metadata.version = "1.0"; @@ -206,7 +178,6 @@ public void marshalsComplexMetadata() throws IOException { } @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void getResourceShouldRetrieveContentByIdentity() throws IOException { byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); @@ -228,7 +199,6 @@ public void getResourceShouldRetrieveContentByIdentity() throws IOException { } @Test // DATAMONGO-1855, DATAMONGO-2240 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void shouldEmitFirstEntryWhenFindFirstRetrievesMoreThanOneResult() throws IOException { Flux upload1 = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); @@ -260,7 +230,6 @@ public void shouldReturnNoGridFsFileWhenAbsent() { } @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void shouldEmitErrorWhenFindOneRetrievesMoreThanOneResult() throws IOException { Flux upload1 = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); @@ -277,7 +246,6 @@ public void shouldEmitErrorWhenFindOneRetrievesMoreThanOneResult() throws IOExce } @Test // DATAMONGO-1855 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void getResourcesByPattern() throws IOException { byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); @@ -300,7 +268,6 @@ public void getResourcesByPattern() throws IOException { } @Test // DATAMONGO-765 - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") public void considersSkipLimitWhenQueryingFiles() { DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); @@ -326,56 +293,15 @@ static class Metadata { String version; } - @Test // - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") - public void xxx() { - - GridFSBucket buckets = GridFSBuckets.create(dbFactory.getMongoDatabase()); - - DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); - DefaultDataBuffer first = factory.wrap("first".getBytes()); - // DefaultDataBuffer second = factory.wrap("second".getBytes()); - - Flux source = Flux.just(first); - - // GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", - // Mono.just(ByteBuffer.wrap("hello".getBytes()))); - GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", - source.map(DataBuffer::asByteBuffer)); - Mono idPublisher = Mono.from(objectIdGridFSUploadPublisher); - idPublisher.as(StepVerifier::create).expectNextCount(1).verifyComplete(); - } - - @Test - @Ignore("https://jira.mongodb.org/browse/JAVARS-224") - public void xxx2() { - - GridFSBucket buckets = GridFSBuckets.create(dbFactory.getMongoDatabase()); - - Flux source = Flux.just(ByteBuffer.wrap("first".getBytes()), ByteBuffer.wrap("second".getBytes())); - Publisher rawSource = toPublisher(ByteBuffer.wrap("first".getBytes()), - ByteBuffer.wrap("second".getBytes())); - - // GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", - // Mono.just(ByteBuffer.wrap("hello".getBytes()))); - // GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", source); - GridFSUploadPublisher objectIdGridFSUploadPublisher = buckets.uploadFromPublisher("foo.xml", rawSource); - Mono.from(objectIdGridFSUploadPublisher).as(StepVerifier::create).expectNextCount(1).verifyComplete(); - - // idPublisher; - } - private static Publisher toPublisher(final ByteBuffer... byteBuffers) { return Publishers.publishAndFlatten(callback -> callback.onResult(Arrays.asList(byteBuffers), null)); } - private ByteBuffer hack(DataBuffer buffer) { - - ByteBuffer byteBuffer = buffer.asByteBuffer(); - ByteBuffer copy = ByteBuffer.allocate(byteBuffer.remaining()); - ByteBufferUtil.copy(byteBuffer, copy, byteBuffer.arrayOffset()); - copy.flip(); - - return copy; + public static String readToString(DataBuffer dataBuffer) { + try { + return FileCopyUtils.copyToString(new InputStreamReader(dataBuffer.asInputStream())); + } catch (IOException e) { + return e.getMessage(); + } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 7bb71cff8b..1c65d2d59a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -41,9 +41,9 @@ */ public class MongoTestUtils { - public static final String CONNECTION_STRING = "mongodb://localhost:27017/?replicaSet=rs0"; // &readPreference=primary&w=majority + public static final String CONNECTION_STRING = "mongodb://localhost:27017/?replicaSet=rs0&w=majority"; - private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/"; + private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/?w=majority"; private static final Version ANY = new Version(9999, 9999, 9999); From 9abf098bdb489ff80505a43a151f3f5e75a3e646 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 27 Jan 2020 09:56:10 +0100 Subject: [PATCH 0049/1381] DATAMONGO-2427 - Polishing. Guard tests. Original pull request: #823. --- .../data/mongodb/gridfs/ReactiveGridFsResource.java | 5 ++++- .../data/mongodb/core/ReactiveMongoTemplateTests.java | 7 +++++++ .../data/mongodb/core/SessionBoundMongoTemplateTests.java | 8 +++++++- .../data/mongodb/core/messaging/ChangeStreamTests.java | 7 +++++++ .../mongodb/gridfs/ReactiveGridFsResourceUnitTests.java | 3 ++- .../data/mongodb/gridfs/ReactiveGridFsTemplateTests.java | 8 +------- .../SimpleMongoRepositoryVersionedEntityTests.java | 8 +++++--- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java index 423226433a..ed71c4a3e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java @@ -34,7 +34,8 @@ import com.mongodb.reactivestreams.client.gridfs.GridFSDownloadPublisher; /** - * Reactive {@link GridFSFile} based {@link Resource} implementation. + * Reactive {@link GridFSFile} based {@link Resource} implementation. Note that the {@link #getDownloadStream() content} + * can be consumed only once. * * @author Mark Paluch * @author Christoph Strobl @@ -63,6 +64,8 @@ public ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher * * @param filename filename of the absent resource. * @param downloadPublisher + * @param dataBufferFactory + * @since 3.0 */ ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher downloadPublisher, DataBufferFactory dataBufferFactory) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index 0c8abe2d5e..38f9d0d03d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -24,6 +24,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Wither; +import org.junit.Rule; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -79,6 +80,8 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.MongoVersion; +import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -99,6 +102,7 @@ public class ReactiveMongoTemplateTests { @Autowired SimpleReactiveMongoDatabaseFactory factory; @Autowired ReactiveMongoTemplate template; @Autowired ConfigurableApplicationContext context; + @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); @Before public void setUp() { @@ -1614,6 +1618,7 @@ public void afterSaveEventContainsSavedObjectUsingInsertAll() { } @Test // DATAMONGO-2012 + @MongoVersion(asOf = "4.0") public void watchesDatabaseCorrectly() throws InterruptedException { Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); @@ -1655,6 +1660,7 @@ public void watchesDatabaseCorrectly() throws InterruptedException { } @Test // DATAMONGO-2012, DATAMONGO-2113 + @MongoVersion(asOf = "4.0") public void resumesAtTimestampCorrectly() throws InterruptedException { Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); @@ -1705,6 +1711,7 @@ public void resumesAtTimestampCorrectly() throws InterruptedException { } @Test // DATAMONGO-2115 + @MongoVersion(asOf = "4.0") public void resumesAtBsonTimestampCorrectly() throws InterruptedException { Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java index c808d7f300..fcce51f500 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java @@ -39,6 +39,7 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.mockito.Mockito; @@ -63,6 +64,7 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.MongoVersion; import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.data.util.Version; @@ -81,9 +83,10 @@ */ public class SessionBoundMongoTemplateTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); public static @ClassRule TestRule replSet = ReplicaSet.required(); + public @Rule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); + MongoClient client; MongoTemplate template; SessionBoundMongoTemplate sessionBoundTemplate; @@ -259,6 +262,7 @@ public void shouldErrorOnLoadLazyDbRefWhenSessionIsClosed() { } @Test // DATAMONGO-2001 + @MongoVersion(asOf = "4.0") public void countShouldWorkInTransactions() { if (!template.collectionExists(Person.class)) { @@ -283,6 +287,7 @@ public void countShouldWorkInTransactions() { } @Test // DATAMONGO-2012 + @MongoVersion(asOf = "4.0") public void countWithGeoInTransaction() { if (!template.collectionExists(Person.class)) { @@ -307,6 +312,7 @@ public void countWithGeoInTransaction() { } @Test // DATAMONGO-2001 + @MongoVersion(asOf = "4.0") public void countShouldReturnIsolatedCount() throws InterruptedException { if (!template.collectionExists(Person.class)) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index 6b5f491eed..7c2e9cc8b8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -39,6 +39,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.springframework.data.annotation.Id; @@ -50,7 +51,10 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.MongoVersion; +import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; +import org.springframework.data.util.Version; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; @@ -65,6 +69,7 @@ public class ChangeStreamTests { public static @ClassRule TestRule replSet = ReplicaSet.required(); + @Rule public MongoVersionRule mongoVersion = MongoVersionRule.atLeast(Version.parse("3.6")); static ThreadPoolExecutor executor; MongoTemplate template; @@ -161,6 +166,7 @@ public void useSimpleAggregationToFilterMessages() throws InterruptedException { } @Test // DATAMONGO-1803 + @MongoVersion(asOf = "4.0") public void useAggregationToFilterMessages() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); @@ -406,6 +412,7 @@ public void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecifie } @Test // DATAMONGO-2012, DATAMONGO-2113 + @MongoVersion(asOf = "4.0") public void resumeAtTimestampCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java index c5a8dcb140..60b2c4f2ed 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResourceUnitTests.java @@ -31,6 +31,8 @@ import com.mongodb.reactivestreams.client.gridfs.GridFSDownloadPublisher; /** + * Unit tests for {@link ReactiveGridFsResource}. + * * @author Christoph Strobl */ class ReactiveGridFsResourceUnitTests { @@ -91,7 +93,6 @@ public void cancel() { } }); - } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 61cfad7a2a..1d0e3aff33 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -27,7 +27,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.ByteBuffer; -import java.util.Arrays; import org.bson.BsonObjectId; import org.bson.Document; @@ -35,7 +34,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.reactivestreams.Publisher; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -58,7 +57,6 @@ import com.mongodb.client.gridfs.model.GridFSFile; import com.mongodb.internal.HexUtils; -import com.mongodb.reactivestreams.client.internal.Publishers; /** * Integration tests for {@link ReactiveGridFsTemplate}. @@ -293,10 +291,6 @@ static class Metadata { String version; } - private static Publisher toPublisher(final ByteBuffer... byteBuffers) { - return Publishers.publishAndFlatten(callback -> callback.onResult(Arrays.asList(byteBuffers), null)); - } - public static String readToString(DataBuffer dataBuffer) { try { return FileCopyUtils.copyToString(new InputStreamReader(dataBuffer.asInputStream())); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java index d56b9d1534..98bdc44f0a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java @@ -21,28 +21,28 @@ import static org.springframework.data.mongodb.core.query.Query.*; import org.junit.Before; +import org.junit.Rule; 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.dao.OptimisticLockingFailureException; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.VersionedPerson; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.mongodb.test.util.MongoVersion; +import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.ClassTypeInformation; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.support.TransactionTemplate; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; /** * @author Christoph Strobl @@ -66,6 +66,8 @@ protected String getDatabaseName() { } } + @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); + @Autowired // private MongoTemplate template; From c83929c2a3704fbfa03e9a3f576830f7e1831ef8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 27 Jan 2020 10:34:27 +0100 Subject: [PATCH 0050/1381] DATAMONGO-2427 - Simplify docker setup. Original pull request: #823. --- .travis.yml | 2 +- Jenkinsfile | 30 +++++++---------------------- ci/openjdk11-mongodb-4.2/Dockerfile | 25 ++++++++++++------------ ci/openjdk13-mongodb-4.2/Dockerfile | 25 ++++++++++++------------ ci/openjdk8-mongodb-4.0/Dockerfile | 25 ++++++++++++------------ ci/openjdk8-mongodb-4.2/Dockerfile | 25 ++++++++++++------------ ci/openjdk8-mongodb-4.3/Dockerfile | 14 -------------- 7 files changed, 60 insertions(+), 86 deletions(-) delete mode 100644 ci/openjdk8-mongodb-4.3/Dockerfile diff --git a/.travis.yml b/.travis.yml index f03d5f2837..bc732f61e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ matrix: env: matrix: - - MONGO_VERSION=4.2.2 + - MONGO_VERSION=4.2.0 - MONGO_VERSION=4.0.14 - MONGO_VERSION=3.6.16 - MONGO_VERSION=3.4.23 diff --git a/Jenkinsfile b/Jenkinsfile index d2e6804c50..5e8d695afe 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,23 +39,7 @@ pipeline { steps { script { - def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.2", "ci/openjdk8-mongodb-4.2/") - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - image.push() - } - } - } - } - stage('Publish JDK 8 + MongoDB 4.3') { - when { - changeset "ci/openjdk8-mongodb-4.3/**" - } - agent { label 'data' } - options { timeout(time: 30, unit: 'MINUTES') } - - steps { - script { - def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.3", "ci/openjdk8-mongodb-4.3/") + def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.2.0", "ci/openjdk8-mongodb-4.2/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } @@ -71,7 +55,7 @@ pipeline { steps { script { - def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.2", "ci/openjdk11-mongodb-4.2/") + def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.2.0", "ci/openjdk11-mongodb-4.2/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } @@ -87,7 +71,7 @@ pipeline { steps { script { - def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.2", "ci/openjdk13-mongodb-4.2/") + def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.2.0", "ci/openjdk13-mongodb-4.2/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } @@ -106,7 +90,7 @@ pipeline { } agent { docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.3:latest' + image 'springci/spring-data-openjdk8-with-mongodb-4.2.0:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } @@ -154,7 +138,7 @@ pipeline { stage("test: mongodb 4.2 (jdk8)") { agent { docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.2:latest' + image 'springci/spring-data-openjdk8-with-mongodb-4.2.0:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } @@ -174,7 +158,7 @@ pipeline { stage("test: baseline (jdk11)") { agent { docker { - image 'springci/spring-data-openjdk11-with-mongodb-4.2:latest' + image 'springci/spring-data-openjdk11-with-mongodb-4.2.0:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } @@ -194,7 +178,7 @@ pipeline { stage("test: baseline (jdk13)") { agent { docker { - image 'springci/spring-data-openjdk13-with-mongodb-4.2:latest' + image 'springci/spring-data-openjdk13-with-mongodb-4.2.0:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } diff --git a/ci/openjdk11-mongodb-4.2/Dockerfile b/ci/openjdk11-mongodb-4.2/Dockerfile index 79218ba5e0..0d92eba78d 100644 --- a/ci/openjdk11-mongodb-4.2/Dockerfile +++ b/ci/openjdk11-mongodb-4.2/Dockerfile @@ -1,14 +1,15 @@ FROM adoptopenjdk/openjdk11:latest -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.2.2 mongodb-org-server=4.2.2 mongodb-org-shell=4.2.2 mongodb-org-mongos=4.2.2 mongodb-org-tools=4.2.2 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* +ENV TZ=Etc/UTC +ENV DEBIAN_FRONTEND=noninteractive + +RUN set -eux; \ + apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ + apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b ; \ + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list; \ + echo ${TZ} > /etc/timezone; + +RUN apt-get update ; \ + apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 ; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; diff --git a/ci/openjdk13-mongodb-4.2/Dockerfile b/ci/openjdk13-mongodb-4.2/Dockerfile index 09221a8cab..7987bdb73c 100644 --- a/ci/openjdk13-mongodb-4.2/Dockerfile +++ b/ci/openjdk13-mongodb-4.2/Dockerfile @@ -1,14 +1,15 @@ FROM adoptopenjdk/openjdk13:latest -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.2.2 mongodb-org-server=4.2.2 mongodb-org-shell=4.2.2 mongodb-org-mongos=4.2.2 mongodb-org-tools=4.2.2 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* +ENV TZ=Etc/UTC +ENV DEBIAN_FRONTEND=noninteractive + +RUN set -eux; \ + apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ + apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b ; \ + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list; \ + echo ${TZ} > /etc/timezone; + +RUN apt-get update ; \ + apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 ; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; diff --git a/ci/openjdk8-mongodb-4.0/Dockerfile b/ci/openjdk8-mongodb-4.0/Dockerfile index 8c2df11650..050a1797f5 100644 --- a/ci/openjdk8-mongodb-4.0/Dockerfile +++ b/ci/openjdk8-mongodb-4.0/Dockerfile @@ -1,14 +1,15 @@ FROM adoptopenjdk/openjdk8:latest -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.0.14 mongodb-org-server=4.0.14 mongodb-org-shell=4.0.14 mongodb-org-mongos=4.0.14 mongodb-org-tools=4.0.14 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* +ENV TZ=Etc/UTC +ENV DEBIAN_FRONTEND=noninteractive + +RUN RUN set -eux; \ + apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ + apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 ; \ + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list; \ + echo ${TZ} > /etc/timezone; + +RUN apt-get update ; \ + apt-get install -y mongodb-org=4.0.14 mongodb-org-server=4.0.14 mongodb-org-shell=4.0.14 mongodb-org-mongos=4.0.14 mongodb-org-tools=4.0.14 ; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; diff --git a/ci/openjdk8-mongodb-4.2/Dockerfile b/ci/openjdk8-mongodb-4.2/Dockerfile index c7e0a4cf84..846a10423b 100644 --- a/ci/openjdk8-mongodb-4.2/Dockerfile +++ b/ci/openjdk8-mongodb-4.2/Dockerfile @@ -1,14 +1,15 @@ FROM adoptopenjdk/openjdk8:latest -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.2.2 mongodb-org-server=4.2.2 mongodb-org-shell=4.2.2 mongodb-org-mongos=4.2.2 mongodb-org-tools=4.2.2 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* +ENV TZ=Etc/UTC +ENV DEBIAN_FRONTEND=noninteractive + +RUN set -eux; \ + apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ + apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b ; \ + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list; \ + echo ${TZ} > /etc/timezone; + +RUN apt-get update ; \ + apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0 ; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; diff --git a/ci/openjdk8-mongodb-4.3/Dockerfile b/ci/openjdk8-mongodb-4.3/Dockerfile deleted file mode 100644 index 73acfd2f65..0000000000 --- a/ci/openjdk8-mongodb-4.3/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM adoptopenjdk/openjdk8:latest - -RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 - -RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b - -RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/development multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.3.list - -RUN apt-get update - -RUN apt-get install -y mongodb-org=4.3.2 mongodb-org-server=4.3.2 mongodb-org-shell=4.3.2 mongodb-org-mongos=4.3.2 mongodb-org-tools=4.3.2 - -RUN apt-get clean \ - && rm -rf /var/lib/apt/lists/* From ecc9f3fd607941c8113a3668d62c01e9f0e54d29 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 27 Jan 2020 08:50:56 +0100 Subject: [PATCH 0051/1381] DATAMONGO-2457 - Fix id type explanation in repository documentation. Original pull request: #829. --- src/main/asciidoc/reference/mongo-repositories.adoc | 5 ++++- src/main/asciidoc/reference/reactive-mongo-repositories.adoc | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index 00f1493b6c..d7a2e01a42 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -28,7 +28,10 @@ public class Person { ---- ==== -Note that the domain type shown in the preceding example has a property named `id` of type `ObjectId`. The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as ID types. Now that we have a domain object, we can define an interface that uses it, as follows: +Note that the domain type shown in the preceding example has a property named `id` of type `String`. The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as ID types. +Please see <> for more information about on how the `id` field is handled in the mapping layer. + +Now that we have a domain object, we can define an interface that uses it, as follows: .Basic repository interface to persist Person entities ==== diff --git a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc index 8ff6737d6e..bef322a882 100644 --- a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc +++ b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc @@ -41,7 +41,10 @@ public class Person { ---- ==== -Note that the entity defined in the preceding example has a property named `id` of type `ObjectId`. The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as id-types. The following example shows how to create an interface that defines queries against the `Person` object from the preceding example: +Note that the entity defined in the preceding example has a property named `id` of type `String`. The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as id-types. +Please see <> for more information about on how the `id` field is handled in the mapping layer. + +The following example shows how to create an interface that defines queries against the `Person` object from the preceding example: .Basic repository interface to persist Person entities ==== From 29053154526dbbdcd5467cbba39f13bb4abc6a8c Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 27 Jan 2020 09:05:43 +0100 Subject: [PATCH 0052/1381] DATAMONGO-2459 - Add sample for passing on limit and offset using reactive repositories. Original pull request: #829. --- .../reference/reactive-mongo-repositories.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc index bef322a882..5d7a9d2f5d 100644 --- a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc +++ b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc @@ -120,6 +120,19 @@ public class PersonRepositoryTests { ---- ==== +The `Page` return type is not supported by reactive repositories as one is able to use the flow controls of the returned reactive types. +Still it is possible to use `Pageable` in derived finder methods, to pass on `sort`, `limit` and `offset` to the database to reduce load and network traffic. +The returned `Flux` will then only emitt data within the declared range. + +.Limit and Offset with reactive repositories +==== +[source,java] +---- +Pageable page = PageRequest.of(1, 10, Sort.by("lastname")); +Flux persons = repository.findByFirstnameOrderByLastname("luke", page); +---- +==== + [[mongo.reactive.repositories.features]] == Features From 708466b323be91c5d125e4adeb8e6f84f05dfd60 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 29 Jan 2020 09:44:50 +0100 Subject: [PATCH 0053/1381] DATAMONGO-2459 - Polishing. Slightly tweak wording. Original pull request: #829 --- .../asciidoc/reference/reactive-mongo-repositories.adoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc index 5d7a9d2f5d..9866878870 100644 --- a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc +++ b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc @@ -96,7 +96,7 @@ class ApplicationConfig extends AbstractReactiveMongoConfiguration { @Override protected String getMappingBasePackage() { - return "com.oreilly.springdata.mongodb" + return "com.oreilly.springdata.mongodb"; } } ---- @@ -120,9 +120,10 @@ public class PersonRepositoryTests { ---- ==== -The `Page` return type is not supported by reactive repositories as one is able to use the flow controls of the returned reactive types. -Still it is possible to use `Pageable` in derived finder methods, to pass on `sort`, `limit` and `offset` to the database to reduce load and network traffic. -The returned `Flux` will then only emitt data within the declared range. +WARNING: The `Page` return type (as in `Mono`) is not supported by reactive repositories. + +It is possible to use `Pageable` in derived finder methods, to pass on `sort`, `limit` and `offset` parameters to the query to reduce load and network traffic. +The returned `Flux` will only emit data within the declared range. .Limit and Offset with reactive repositories ==== From 80da9e21ed083dae61fde326e22dbf32b25bde3e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 17 Jan 2020 10:18:54 +0100 Subject: [PATCH 0054/1381] DATAMONGO-2406 - Derived reactive deleteBy query execution should allow Mono result. Mono is now a supported return type of derived reactive deleteBy queries like: Mono deleteByLastname(String lastname); Original pull request: #825. --- .../query/ReactiveMongoQueryExecution.java | 9 +++++++++ .../repository/ReactiveMongoRepositoryTests.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index d3b3f186f0..e3b8e9a49f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; +import org.reactivestreams.Publisher; import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.domain.Pageable; @@ -168,6 +169,10 @@ public Object convert(Object source) { ReturnedType returnedType = processor.getReturnedType(); + if (returnsMonoVoid(returnedType)) { + return Flux.from((Publisher) source).then(); + } + if (ClassUtils.isPrimitiveOrWrapper(returnedType.getReturnedType())) { return source; } @@ -182,4 +187,8 @@ public Object convert(Object source) { return processor.processResult(source, converter); } } + + static boolean returnsMonoVoid(ReturnedType returnedType) { + return returnedType.getReturnedType() == Void.class; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index 1f92d94663..e38c6782cc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -17,6 +17,8 @@ import static org.assertj.core.api.Assertions.*; import static org.springframework.data.domain.Sort.Direction.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; +import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.test.util.Assertions.assertThat; import lombok.Data; @@ -575,6 +577,18 @@ public void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { .expectNext("lastname").verifyComplete(); } + @Test // DATAMONGO-2406 + public void deleteByShouldHandleVoidResultTypeCorrectly() { + + repository.deleteByLastname(dave.getLastname()) // + .as(StepVerifier::create) // + .verifyComplete(); + + template.find(query(where("lastname").is(dave.getLastname())), Person.class) // + .as(StepVerifier::create) // + .verifyComplete(); + } + interface ReactivePersonRepository extends ReactiveMongoRepository, ReactiveQuerydslPredicateExecutor { @@ -645,6 +659,8 @@ interface ReactivePersonRepository @Query(value = "{_id:?0}") Mono findDocumentById(String id); + + Mono deleteByLastname(String lastname); } interface ReactiveContactRepository extends ReactiveMongoRepository {} From 0a2ea88f3c96b4555f98bb4967f7e8e98e755dae Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 29 Jan 2020 09:56:54 +0100 Subject: [PATCH 0055/1381] DATAMONGO-2406 - Polishing. Add optimization for Mono. Original pull request: #825. --- .../query/ReactiveMongoQueryExecution.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index e3b8e9a49f..111005beeb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -18,8 +18,10 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import org.reactivestreams.Publisher; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.domain.Pageable; @@ -169,8 +171,15 @@ public Object convert(Object source) { ReturnedType returnedType = processor.getReturnedType(); - if (returnsMonoVoid(returnedType)) { - return Flux.from((Publisher) source).then(); + if (isVoid(returnedType)) { + + if (source instanceof Mono) { + return ((Mono) source).then(); + } + + if (source instanceof Publisher) { + return Flux.from((Publisher) source).then(); + } } if (ClassUtils.isPrimitiveOrWrapper(returnedType.getReturnedType())) { @@ -188,7 +197,7 @@ public Object convert(Object source) { } } - static boolean returnsMonoVoid(ReturnedType returnedType) { - return returnedType.getReturnedType() == Void.class; + static boolean isVoid(ReturnedType returnedType) { + return returnedType.getReturnedType().equals(Void.class); } } From c56a13ad009805946bd38d9fb2b1334259fbfff3 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 17 Jan 2020 15:52:05 +0100 Subject: [PATCH 0056/1381] DATAMONGO-1997 - Add support to return the single deleted item for a deleteBy query method. Added support for: @Nullable Person deleteSingleByLastname(String lastname); Optional deleteByBirthdate(Date birthdate); Mono deleteSinglePersonByLastname(String lastname); Original pull request: #826. --- .../repository/query/MongoQueryExecution.java | 5 +++ .../query/ReactiveMongoQueryExecution.java | 4 ++ ...tractPersonRepositoryIntegrationTests.java | 7 ++++ .../mongodb/repository/PersonRepository.java | 3 ++ .../ReactiveMongoRepositoryTests.java | 26 ++++++++++++ .../query/MongoQueryExecutionUnitTests.java | 42 ++++++++++++++++++- .../reference/mongo-repositories.adoc | 15 +++++-- 7 files changed, 96 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index be422616e2..2f6766651e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -39,6 +39,7 @@ import org.springframework.data.util.TypeInformation; import com.mongodb.client.result.DeleteResult; +import org.springframework.util.ClassUtils; /** * Set of classes to contain query execution strategies. Depending (mostly) on the return type of a @@ -255,6 +256,10 @@ public Object execute(Query query) { return operations.findAllAndRemove(query, type, collectionName); } + if(method.isQueryForEntity() && !ClassUtils.isPrimitiveOrWrapper(method.getReturnedObjectType())) { + return operations.findAndRemove(query, type, collectionName); + } + DeleteResult writeResult = operations.remove(query, type, collectionName); return writeResult.wasAcknowledged() ? writeResult.getDeletedCount() : 0L; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 111005beeb..863b904eb3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -129,6 +129,10 @@ public Object execute(Query query, Class type, String collection) { return operations.findAllAndRemove(query, type, collection); } + if(method.isQueryForEntity() && !ClassUtils.isPrimitiveOrWrapper(method.getReturnedObjectType())) { + return operations.findAndRemove(query, type, collection); + } + return operations.remove(query, type, collection) .map(deleteResult -> deleteResult.wasAcknowledged() ? deleteResult.getDeletedCount() : 0L); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index b4f4d824a7..52446d4405 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -741,6 +741,13 @@ public void deleteByShouldReturnNumberOfDocumentsRemovedIfReturnTypeIsLong() { assertThat(repository.deletePersonByLastname("Beauford")).isEqualTo(1L); } + @Test // DATAMONGO-1997 + public void deleteByShouldResultWrappedInOptionalCorrectly() { + + assertThat(repository.deleteOptionalByLastname("Beauford")).isPresent(); + assertThat(repository.deleteOptionalByLastname("dorfuaeB")).isNotPresent(); + } + @Test // DATAMONGO-566 public void deleteByShouldReturnZeroInCaseNoDocumentHasBeenRemovedAndReturnTypeIsNumber() { assertThat(repository.deletePersonByLastname("dorfuaeB")).isEqualTo(0L); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index eb5fb07486..b65bd3d8ce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -264,6 +264,9 @@ public interface PersonRepository extends MongoRepository, Query // DATAMONGO-566 Long deletePersonByLastname(String lastname); + // DATAMONGO-1997 + Optional deleteOptionalByLastname(String lastname); + // DATAMONGO-566 @Query(value = "{ 'lastname' : ?0 }", delete = true) List removeByLastnameUsingAnnotatedQuery(String lastname); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index e38c6782cc..ae294d5eb6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -589,6 +589,28 @@ public void deleteByShouldHandleVoidResultTypeCorrectly() { .verifyComplete(); } + @Test // DATAMONGO-1997 + public void deleteByShouldAllowDeletedCountAsResult() { + + repository.deleteCountByLastname(dave.getLastname()) // + .as(StepVerifier::create) // + .expectNext(2L) // + .verifyComplete(); + } + + @Test // DATAMONGO-1997 + public void deleteByShouldAllowSingleDocumentRemovalCorrectly() { + + repository.deleteSinglePersonByLastname(carter.getLastname()) // + .as(StepVerifier::create) // + .expectNext(carter) // + .verifyComplete(); + + repository.deleteSinglePersonByLastname("dorfuaeB") // + .as(StepVerifier::create) // + .verifyComplete(); + } + interface ReactivePersonRepository extends ReactiveMongoRepository, ReactiveQuerydslPredicateExecutor { @@ -661,6 +683,10 @@ interface ReactivePersonRepository Mono findDocumentById(String id); Mono deleteByLastname(String lastname); + + Mono deleteCountByLastname(String lastname); + + Mono deleteSinglePersonByLastname(String lastname); } interface ReactiveContactRepository extends ReactiveMongoRepository {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java index 18d3f8f725..3f7ad9437e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java @@ -16,13 +16,13 @@ package org.springframework.data.mongodb.repository.query; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; +import java.util.Optional; import org.junit.Before; import org.junit.Test; @@ -68,6 +68,7 @@ * @author Mark Paluch * @author Oliver Gierke * @author Artyom Gabeev + * @author Christoph Strobl * @soundtrack U Can't Touch This - MC Hammer */ @RunWith(MockitoJUnitRunner.class) @@ -181,6 +182,9 @@ public void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() { @Test // DATAMONGO-2351 public void acknowledgedDeleteReturnsDeletedCount() { + Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteAllByLastname", String.class); + MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); + when(mongoOperationsMock.remove(any(Query.class), any(Class.class), anyString())) .thenReturn(DeleteResult.acknowledged(10)); @@ -190,14 +194,48 @@ public void acknowledgedDeleteReturnsDeletedCount() { @Test // DATAMONGO-2351 public void unacknowledgedDeleteReturnsZeroDeletedCount() { + Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteAllByLastname", String.class); + MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); + when(mongoOperationsMock.remove(any(Query.class), any(Class.class), anyString())) .thenReturn(DeleteResult.unacknowledged()); assertThat(new DeleteExecution(mongoOperationsMock, queryMethod).execute(new Query())).isEqualTo(0L); } + @Test // DATAMONGO-1997 + public void deleteExecutionWithEntityReturnTypeTriggersFindAndRemove() { + + Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteByLastname", String.class); + MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); + + Person person = new Person(); + + when(mongoOperationsMock.findAndRemove(any(Query.class), any(Class.class), anyString())).thenReturn(person); + + assertThat(new DeleteExecution(mongoOperationsMock, queryMethod).execute(new Query())).isEqualTo(person); + } +// @Test // DATAMONGO-1997 +// public void deleteExecutionWrapsEmptyResultInOptionalCorrectly() { +// +// Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteByLastname", String.class); +// MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); +// +// Person person = new Person(); +// +// when(mongoOperationsMock.findAndRemove(any(Query.class), any(Class.class), anyString())).thenReturn(null); +// +// assertThat(new DeleteExecution(mongoOperationsMock, queryMethod).execute(new Query())).isEqualTo(Optional.empty()); +// } + interface PersonRepository extends Repository { GeoPage findByLocationNear(Point point, Distance distance, Pageable pageable); + + Long deleteAllByLastname(String lastname); + + Person deleteByLastname(String lastname); + + Optional deletePersonByLastname(String lastname); } } diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index d7a2e01a42..69f5d71564 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -301,15 +301,22 @@ The keywords in the preceding table can be used in conjunction with `delete…By ---- public interface PersonRepository extends MongoRepository { - List deleteByLastname(String lastname); + List deleteByLastname(String lastname); <1> - Long deletePersonByLastname(String lastname); + Long deletePersonByLastname(String lastname); <2> + + @Nullable + Person deleteSingleByLastname(String lastname); <3> + + Optional deleteByBirthdate(Date birthdate); <4> } ---- +<1> Using a return type of `List` retrieves and returns all matching documents before actually deleting them. +<2> A numeric return type directly removes the matching documents, returning the total number of documents removed. +<3> A single domain type result retrieves and removes the first matching document. +<4> Same as in 3 but wrapped in an `Optional` type. ==== -Using a return type of `List` retrieves and returns all matching documents before actually deleting them. A numeric return type directly removes the matching documents, returning the total number of documents removed. - [[mongodb.repositories.queries.geo-spatial]] === Geo-spatial Repository Queries From 44017485fc0a77f9d78660eab31b989cfc18ab34 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 29 Jan 2020 10:25:28 +0100 Subject: [PATCH 0057/1381] DATAMONGO-1997 - Polishing. Tweak documentation. Reformat code. Remove commented code. Original pull request: #826. --- .../repository/query/MongoQueryExecution.java | 4 ++-- .../query/ReactiveMongoQueryExecution.java | 2 +- .../query/MongoQueryExecutionUnitTests.java | 16 +--------------- .../asciidoc/reference/mongo-repositories.adoc | 8 ++++---- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index 2f6766651e..3b5db06913 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -37,9 +37,9 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.repository.support.PageableExecutionUtils; import org.springframework.data.util.TypeInformation; +import org.springframework.util.ClassUtils; import com.mongodb.client.result.DeleteResult; -import org.springframework.util.ClassUtils; /** * Set of classes to contain query execution strategies. Depending (mostly) on the return type of a @@ -256,7 +256,7 @@ public Object execute(Query query) { return operations.findAllAndRemove(query, type, collectionName); } - if(method.isQueryForEntity() && !ClassUtils.isPrimitiveOrWrapper(method.getReturnedObjectType())) { + if (method.isQueryForEntity() && !ClassUtils.isPrimitiveOrWrapper(method.getReturnedObjectType())) { return operations.findAndRemove(query, type, collectionName); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 863b904eb3..39b7ac1ade 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -129,7 +129,7 @@ public Object execute(Query query, Class type, String collection) { return operations.findAllAndRemove(query, type, collection); } - if(method.isQueryForEntity() && !ClassUtils.isPrimitiveOrWrapper(method.getReturnedObjectType())) { + if (method.isQueryForEntity() && !ClassUtils.isPrimitiveOrWrapper(method.getReturnedObjectType())) { return operations.findAndRemove(query, type, collection); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java index 3f7ad9437e..36e59b6135 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java @@ -22,13 +22,13 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; -import java.util.Optional; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.geo.Distance; @@ -215,18 +215,6 @@ public void deleteExecutionWithEntityReturnTypeTriggersFindAndRemove() { assertThat(new DeleteExecution(mongoOperationsMock, queryMethod).execute(new Query())).isEqualTo(person); } -// @Test // DATAMONGO-1997 -// public void deleteExecutionWrapsEmptyResultInOptionalCorrectly() { -// -// Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteByLastname", String.class); -// MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); -// -// Person person = new Person(); -// -// when(mongoOperationsMock.findAndRemove(any(Query.class), any(Class.class), anyString())).thenReturn(null); -// -// assertThat(new DeleteExecution(mongoOperationsMock, queryMethod).execute(new Query())).isEqualTo(Optional.empty()); -// } interface PersonRepository extends Repository { @@ -235,7 +223,5 @@ interface PersonRepository extends Repository { Long deleteAllByLastname(String lastname); Person deleteByLastname(String lastname); - - Optional deletePersonByLastname(String lastname); } } diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index 69f5d71564..04715cb299 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -301,14 +301,14 @@ The keywords in the preceding table can be used in conjunction with `delete…By ---- public interface PersonRepository extends MongoRepository { - List deleteByLastname(String lastname); <1> + List deleteByLastname(String lastname); <1> - Long deletePersonByLastname(String lastname); <2> + Long deletePersonByLastname(String lastname); <2> @Nullable - Person deleteSingleByLastname(String lastname); <3> + Person deleteSingleByLastname(String lastname); <3> - Optional deleteByBirthdate(Date birthdate); <4> + Optional deleteByBirthdate(Date birthdate); <4> } ---- <1> Using a return type of `List` retrieves and returns all matching documents before actually deleting them. From c21b35973dad64dd6852fc79ab1cc7eb8620f3c8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 29 Jan 2020 10:36:45 +0100 Subject: [PATCH 0058/1381] DATAMONGO-2462 - Move off deprecated EntityInstantiators. We now use the newly introduced EntityInstantiator at o.s.d.mapping.model and moved off the deprecated one in o.s.d.convert. --- .../data/mongodb/core/convert/AbstractMongoConverter.java | 7 +++---- .../data/mongodb/core/convert/MappingMongoConverter.java | 3 ++- .../repository/query/AbstractReactiveMongoQuery.java | 2 +- .../repository/query/DtoInstantiatingConverter.java | 4 ++-- .../repository/query/ReactiveMongoQueryExecution.java | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java index b6d90aeb0e..d4546b9e10 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java @@ -26,7 +26,7 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.convert.ConverterBuilder; import org.springframework.data.convert.CustomConversions; -import org.springframework.data.convert.EntityInstantiators; +import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToObjectIdConverter; import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter; import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter; @@ -107,9 +107,8 @@ private void initializeConverters() { if (!conversionService.canConvert(ObjectId.class, Date.class)) { - conversionService.addConverter( - ConverterBuilder.reading(ObjectId.class, Date.class, objectId -> new Date(objectId.getTimestamp())) - .getReadingConverter()); + conversionService.addConverter(ConverterBuilder + .reading(ObjectId.class, Date.class, objectId -> new Date(objectId.getTimestamp())).getReadingConverter()); } conversionService 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 f189938d11..5e87e77ec4 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 @@ -37,13 +37,13 @@ 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; import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.data.convert.EntityInstantiator; import org.springframework.data.convert.TypeMapper; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.MappingException; @@ -53,6 +53,7 @@ import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.ConvertingPropertyAccessor; import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator; +import org.springframework.data.mapping.model.EntityInstantiator; import org.springframework.data.mapping.model.ParameterValueProvider; import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider; import org.springframework.data.mapping.model.PropertyValueProvider; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index 81b8305ee2..69c834e4fa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -21,7 +21,7 @@ import org.bson.Document; import org.reactivestreams.Publisher; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.EntityInstantiators; +import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithProjection; import org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithQuery; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java index a7c2a9a44c..c7f4e2a23e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java @@ -16,8 +16,6 @@ package org.springframework.data.mongodb.repository.query; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.EntityInstantiator; -import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -25,6 +23,8 @@ import org.springframework.data.mapping.PreferredConstructor.Parameter; import org.springframework.data.mapping.SimplePropertyHandler; import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.model.EntityInstantiator; +import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mapping.model.ParameterValueProvider; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 39b7ac1ade..9feb4a9d96 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -23,12 +23,12 @@ import org.reactivestreams.Publisher; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Range; import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.Point; +import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; From 0bc0fff24ec29b1bd8b0def1f9555802f55c4b7c Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 21 Jan 2020 13:25:25 +0100 Subject: [PATCH 0059/1381] DATAMONGO-2365 - Pass on index name to query hint. Original pull request: #828. --- .../data/mongodb/core/MongoTemplate.java | 18 ++++++- .../mongodb/core/ReactiveMongoTemplate.java | 18 ++++++- .../data/mongodb/core/query/Query.java | 7 +-- .../data/mongodb/util/BsonUtils.java | 48 ++++++++++++++++++- .../mongodb/core/MongoTemplateUnitTests.java | 13 +++++ .../core/QueryCursorPreparerUnitTests.java | 11 +++++ .../core/ReactiveMongoTemplateUnitTests.java | 13 +++++ 7 files changed, 118 insertions(+), 10 deletions(-) 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 01a252b807..393182f2cc 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 @@ -114,6 +114,7 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; import org.springframework.data.mongodb.core.validation.Validator; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.util.CloseableIterator; import org.springframework.data.util.Optionals; @@ -1156,7 +1157,13 @@ public long count(Query query, @Nullable Class entityClass, String collection options.skip((int) query.getSkip()); } if (StringUtils.hasText(query.getHint())) { - options.hint(Document.parse(query.getHint())); + + String hint = query.getHint(); + if(BsonUtils.isJsonDocument(hint)) { + options = options.hint(BsonUtils.parse(hint, mongoDbFactory)); + } else { + options = options.hintString(hint); + } } Document document = queryMapper.getMappedObject(query.getQueryObject(), @@ -3276,7 +3283,14 @@ public FindIterable prepare(FindIterable cursor) { } if (StringUtils.hasText(query.getHint())) { - cursorToUse = cursorToUse.hint(Document.parse(query.getHint())); + + String hint = query.getHint(); + + if(BsonUtils.isJsonDocument(hint)) { + cursorToUse = cursorToUse.hint(BsonUtils.parse(hint, mongoDbFactory)); + } else { + cursorToUse = cursorToUse.hintString(hint); + } } if (meta.hasValues()) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 257839f4a5..600cceffdd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -21,6 +21,7 @@ import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.util.BsonUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -1279,7 +1280,13 @@ public Mono count(Query query, @Nullable Class entityClass, String coll options.skip((int) query.getSkip()); } if (StringUtils.hasText(query.getHint())) { - options.hint(Document.parse(query.getHint())); + + String hint = query.getHint(); + if(BsonUtils.isJsonDocument(hint)) { + options = options.hint(BsonUtils.parse(hint, mongoDatabaseFactory)); + } else { + options = options.hintString(hint); + } } operations.forType(entityClass).getCollation(query).map(Collation::toMongoCollation) // @@ -3276,7 +3283,14 @@ public FindPublisher prepare(FindPublisher findPublisher) { } if (StringUtils.hasText(query.getHint())) { - findPublisherToUse = findPublisherToUse.hint(Document.parse(query.getHint())); + + String hint = query.getHint(); + + if(BsonUtils.isJsonDocument(hint)) { + findPublisherToUse = findPublisherToUse.hint(BsonUtils.parse(hint, mongoDatabaseFactory)); + } else { + findPublisherToUse = findPublisherToUse.hintString(hint); + } } if (meta.hasValues()) { 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 0de6f00760..6172a41986 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 @@ -141,14 +141,13 @@ public Query limit(int limit) { } /** - * Configures the query to use the given hint when being executed. {@code hint} is parsed as {@link Document}. + * Configures the query to use the given hint when being executed. The {@code hint} can either be an index name or a + * json {@link Document} representation. * * @param hint must not be {@literal null} or empty. * @return * @see Document#parse(String) - * @deprecated since 2.2, use {@link #withHint(Document)} */ - @Deprecated public Query withHint(String hint) { Assert.hasText(hint, "Hint must not be empty or null!"); @@ -312,10 +311,8 @@ public int getLimit() { /** * @return - * @deprecated since 2.2. Return type to be changed to {@link Document}. */ @Nullable - @Deprecated public String getHint() { return hint; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index 3e6f6887ac..6ecd474d1f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -25,11 +25,13 @@ import org.bson.BsonValue; import org.bson.Document; +import org.bson.codecs.DocumentCodec; import org.bson.conversions.Bson; import org.bson.json.JsonParseException; - import org.springframework.core.convert.converter.Converter; +import org.springframework.data.mongodb.CodecRegistryProvider; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -175,6 +177,50 @@ public static String toJson(@Nullable Document source) { } } + /** + * Check if a given String looks like {@link Document#parse(String) parsable} json. + * + * @param value can be {@literal null}. + * @return {@literal true} if the given value looks like a json document. + * @since 3.0 + */ + public static boolean isJsonDocument(@Nullable String value) { + return StringUtils.hasText(value) && (value.startsWith("{") && value.endsWith("}")); + } + + /** + * Check if a given String looks like {@link org.bson.BsonArray#parse(String) parsable} json array. + * + * @param value can be {@literal null}. + * @return {@literal true} if the given value looks like a json array. + * @since 3.0 + */ + public static boolean isJsonArray(@Nullable String value) { + return StringUtils.hasText(value) && (value.startsWith("[") && value.endsWith("]")); + } + + /** + * Parse the given {@literal json} to {@link Document} applying transformations as specified by a potentially given + * {@link org.bson.codecs.Codec}. + * + * @param json must not be {@literal null}. + * @param codecRegistryProvider can be {@literal null}. In that case the default {@link DocumentCodec} is used. + * @return never {@literal null}. + * @throws IllegalArgumentException if the required argument is {@literal null}. + * @since 3.0 + */ + public static Document parse(String json, @Nullable CodecRegistryProvider codecRegistryProvider) { + + Assert.notNull(json, "Json must not be null!"); + + if (codecRegistryProvider == null) { + return Document.parse(json); + } + + return Document.parse(json, codecRegistryProvider.getCodecFor(Document.class) + .orElseGet(() -> new DocumentCodec(codecRegistryProvider.getCodecRegistry()))); + } + @Nullable private static String toJson(@Nullable Object value) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index b6a4ac6b44..31ca013cdb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -19,6 +19,7 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.*; +import com.mongodb.MongoClientSettings; import lombok.Data; import java.math.BigInteger; @@ -158,6 +159,7 @@ public void beforeEach() { when(findIterable.iterator()).thenReturn(cursor); when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); + when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); when(db.getCollection(any(String.class), eq(Document.class))).thenReturn(collection); when(db.runCommand(any(), any(Class.class))).thenReturn(commandResultDocument); when(collection.find(any(org.bson.Document.class), any(Class.class))).thenReturn(findIterable); @@ -955,6 +957,17 @@ public void countShouldApplyQueryHintIfPresent() { assertThat(options.getValue().getHint()).isEqualTo(queryHint); } + @Test // DATAMONGO-2365 + public void countShouldApplyQueryHintAsIndexNameIfPresent() { + + template.count(new BasicQuery("{}").withHint("idx-1"), AutogenerateableId.class); + + ArgumentCaptor options = ArgumentCaptor.forClass(CountOptions.class); + verify(collection).countDocuments(any(), options.capture()); + + assertThat(options.getValue().getHintString()).isEqualTo("idx-1"); + } + @Test // DATAMONGO-1733 public void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() { 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 5404d7c000..c36fbd4235 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 @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; +import com.mongodb.MongoClientSettings; import org.bson.Document; import org.junit.Before; import org.junit.Test; @@ -53,6 +54,7 @@ public class QueryCursorPreparerUnitTests { public void setUp() { when(factory.getExceptionTranslator()).thenReturn(exceptionTranslatorMock); + when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); when(cursor.batchSize(anyInt())).thenReturn(cursor); when(cursor.comment(anyString())).thenReturn(cursor); when(cursor.maxTime(anyLong(), any())).thenReturn(cursor); @@ -70,6 +72,15 @@ public void appliesHintsCorrectly() { verify(cursor).hint(new Document("age", 1)); } + @Test // DATAMONGO-2365 + public void appliesIndexNameAsHintCorrectly() { + + Query query = query(where("foo").is("bar")).withHint("idx-1"); + prepare(query); + + verify(cursor).hintString("idx-1"); + } + @Test // DATAMONGO-2319 public void appliesDocumentHintsCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 6bd65c2f16..82ee812651 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; +import com.mongodb.MongoClientSettings; import lombok.Data; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -128,6 +129,7 @@ public class ReactiveMongoTemplateUnitTests { public void beforeEach() { when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); + when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); when(factory.getMongoDatabase()).thenReturn(db); when(db.getCollection(any())).thenReturn(collection); when(db.getCollection(any(), any())).thenReturn(collection); @@ -434,6 +436,17 @@ public void countShouldApplyQueryHintIfPresent() { assertThat(options.getValue().getHint()).isEqualTo(queryHint); } + @Test // DATAMONGO-2365 + public void countShouldApplyQueryHintAsIndexNameIfPresent() { + + template.count(new Query().withHint("idx-1"), Person.class, "star-wars").subscribe(); + + ArgumentCaptor options = ArgumentCaptor.forClass(CountOptions.class); + verify(collection).countDocuments(any(), options.capture()); + + assertThat(options.getValue().getHintString()).isEqualTo("idx-1"); + } + @Test // DATAMONGO-2215 public void updateShouldApplyArrayFilters() { From c7f9274480e163369bbfab5053c4944a3103ba5e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 21 Jan 2020 16:14:08 +0100 Subject: [PATCH 0060/1381] DATAMONGO-2365 - Extract common functionality to centralized component. Share common code paths between reactive and imperative implementation. Original pull request: #828. --- .../data/mongodb/core/MongoTemplate.java | 217 ++---- .../data/mongodb/core/QueryOperations.java | 661 ++++++++++++++++++ .../mongodb/core/ReactiveMongoTemplate.java | 208 ++---- 3 files changed, 781 insertions(+), 305 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java 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 393182f2cc..743724a644 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 @@ -30,9 +30,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import org.bson.BsonValue; import org.bson.Document; -import org.bson.codecs.Codec; import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,8 +52,6 @@ import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Metric; -import org.springframework.data.mapping.PropertyPath; -import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.MongoDatabaseUtils; @@ -64,14 +60,15 @@ import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; import org.springframework.data.mongodb.core.EntityOperations.AdaptibleEntity; -import org.springframework.data.mongodb.core.MappedDocument.MappedUpdate; +import org.springframework.data.mongodb.core.QueryOperations.CountContext; +import org.springframework.data.mongodb.core.QueryOperations.DeleteContext; +import org.springframework.data.mongodb.core.QueryOperations.DistinctQueryContext; +import org.springframework.data.mongodb.core.QueryOperations.QueryContext; +import org.springframework.data.mongodb.core.QueryOperations.UpdateContext; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; import org.springframework.data.mongodb.core.aggregation.AggregationResults; -import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; -import org.springframework.data.mongodb.core.aggregation.Fields; -import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -196,6 +193,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, private final SpelAwareProxyProjectionFactory projectionFactory; private final EntityOperations operations; private final PropertyOperations propertyOperations; + private final QueryOperations queryOperations; private @Nullable WriteConcern writeConcern; private WriteConcernResolver writeConcernResolver = DefaultWriteConcernResolver.INSTANCE; @@ -247,6 +245,7 @@ public MongoTemplate(MongoDatabaseFactory mongoDbFactory, @Nullable MongoConvert this.projectionFactory = new SpelAwareProxyProjectionFactory(); this.operations = new EntityOperations(this.mongoConverter.getMappingContext()); this.propertyOperations = new PropertyOperations(this.mongoConverter.getMappingContext()); + this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, mongoDbFactory); // We always have a mapping context in the converter, whether it's a simple one or not mappingContext = this.mongoConverter.getMappingContext(); @@ -285,6 +284,7 @@ private MongoTemplate(MongoDatabaseFactory dbFactory, MongoTemplate that) { this.mappingContext = that.mappingContext; this.operations = that.operations; this.propertyOperations = that.propertyOperations; + this.queryOperations = that.queryOperations; } /** @@ -827,10 +827,11 @@ public boolean exists(Query query, @Nullable Class entityClass, String collec } Assert.notNull(collectionName, "CollectionName must not be null!"); - Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), getPersistentEntity(entityClass)); + QueryContext queryContext = queryOperations.createQueryContext(query); + Document mappedQuery = queryContext.getMappedQuery(entityClass, this::getPersistentEntity); - return execute(collectionName, new ExistsCallback(mappedQuery, - operations.forType(entityClass).getCollation(query).map(Collation::toMongoCollation).orElse(null))); + return execute(collectionName, + new ExistsCallback(mappedQuery, queryContext.getCollation(entityClass).orElse(null))); } // Find methods that take a Query to express the query and that return a List of objects. @@ -903,13 +904,11 @@ public List findDistinct(Query query, String field, String collectionName Assert.notNull(resultClass, "ResultClass must not be null!"); MongoPersistentEntity entity = entityClass != Object.class ? getPersistentEntity(entityClass) : null; + DistinctQueryContext distinctQueryContext = queryOperations.distincQueryContext(query, field); - Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), entity); - String mappedFieldName = queryMapper.getMappedFields(new Document(field, 1), entity).keySet().iterator().next(); - - Class mongoDriverCompatibleType = getMongoDbFactory().getCodecFor(resultClass) // - .map(Codec::getEncoderClass) // - .orElse((Class) BsonValue.class); + Document mappedQuery = distinctQueryContext.getMappedQuery(entity); + String mappedFieldName = distinctQueryContext.getMappedFieldName(entity); + Class mongoDriverCompatibleType = distinctQueryContext.getDriverCompatibleClass(resultClass); MongoIterable result = execute(collectionName, (collection) -> { @@ -924,12 +923,9 @@ public List findDistinct(Query query, String field, String collectionName } DistinctIterable iterable = collection.distinct(mappedFieldName, mappedQuery, mongoDriverCompatibleType); + distinctQueryContext.applyCollation(entityClass, iterable::collation); - return operations.forType(entityClass) // - .getCollation(query) // - .map(Collation::toMongoCollation) // - .map(iterable::collation) // - .orElse(iterable); + return iterable; }); if (resultClass == Object.class || mongoDriverCompatibleType != resultClass) { @@ -938,7 +934,7 @@ public List findDistinct(Query query, String field, String collectionName DefaultDbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory); result = result.map((source) -> converter.mapValueToTargetType(source, - getMostSpecificConversionTargetType(resultClass, entityClass, field), dbRefResolver)); + distinctQueryContext.getMostSpecificConversionTargetType(resultClass, entityClass), dbRefResolver)); } try { @@ -948,32 +944,6 @@ public List findDistinct(Query query, String field, String collectionName } } - /** - * @param userType must not be {@literal null}. - * @param domainType must not be {@literal null}. - * @param field must not be {@literal null}. - * @return the most specific conversion target type depending on user preference and domain type property. - * @since 2.1 - */ - private static Class getMostSpecificConversionTargetType(Class userType, Class domainType, String field) { - - Class conversionTargetType = userType; - try { - - Class propertyType = PropertyPath.from(field, domainType).getLeafProperty().getLeafType(); - - // use the more specific type but favor UserType over property one - if (ClassUtils.isAssignable(userType, propertyType)) { - conversionTargetType = propertyType; - } - - } catch (PropertyReferenceException e) { - // just don't care about it as we default to Object.class anyway. - } - - return conversionTargetType; - } - @Override public GeoResults geoNear(NearQuery near, Class entityClass) { return geoNear(near, entityClass, getCollectionName(entityClass)); @@ -1088,10 +1058,11 @@ public T findAndReplace(Query query, S replacement, FindAndReplaceOptions Assert.isTrue(query.getSkip() <= 0, "Query must not define skip."); MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityType); + QueryContext queryContext = queryOperations.createQueryContext(query); - Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), entity); - Document mappedFields = queryMapper.getMappedFields(query.getFieldsObject(), entity); - Document mappedSort = queryMapper.getMappedSort(query.getSortObject(), entity); + Document mappedQuery = queryContext.getMappedQuery(entity); + Document mappedFields = queryContext.getMappedFields(entity); + Document mappedSort = queryContext.getMappedSort(entity); replacement = maybeCallBeforeConvert(replacement, collectionName); Document mappedReplacement = operations.forEntity(replacement).toMappedDocument(this.mongoConverter).getDocument(); @@ -1100,8 +1071,7 @@ public T findAndReplace(Query query, S replacement, FindAndReplaceOptions maybeCallBeforeSave(replacement, mappedReplacement, collectionName); return doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, - operations.forType(entityType).getCollation(query).map(Collation::toMongoCollation).orElse(null), entityType, - mappedReplacement, options, resultType); + queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, resultType); } // Find methods that take a Query to express the query and that return a single object that is also removed from the @@ -1147,29 +1117,12 @@ public long count(Query query, @Nullable Class entityClass, String collection Assert.notNull(query, "Query must not be null!"); Assert.hasText(collectionName, "Collection name must not be null or empty!"); - CountOptions options = new CountOptions(); - query.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation); + CountContext countContext = queryOperations.countQueryContext(query); - if (query.getLimit() > 0) { - options.limit(query.getLimit()); - } - if (query.getSkip() > 0) { - options.skip((int) query.getSkip()); - } - if (StringUtils.hasText(query.getHint())) { - - String hint = query.getHint(); - if(BsonUtils.isJsonDocument(hint)) { - options = options.hint(BsonUtils.parse(hint, mongoDbFactory)); - } else { - options = options.hintString(hint); - } - } + CountOptions options = countContext.getCountOptions(entityClass); + Document mappedQuery = countContext.getMappedQuery(entityClass, mappingContext::getPersistentEntity); - Document document = queryMapper.getMappedObject(query.getQueryObject(), - Optional.ofNullable(entityClass).map(it -> mappingContext.getPersistentEntity(entityClass))); - - return doCount(collectionName, document, options); + return doCount(collectionName, mappedQuery, options); } @SuppressWarnings("ConstantConditions") @@ -1617,33 +1570,20 @@ protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefini } MongoPersistentEntity entity = entityClass == null ? null : getPersistentEntity(entityClass); - increaseVersionForUpdateIfNecessary(entity, update); - UpdateOptions opts = new UpdateOptions(); - opts.upsert(upsert); + UpdateContext updateContext = multi ? queryOperations.updateContext(update, query, upsert) + : queryOperations.updateSingleContext(update, query, upsert); + updateContext.increaseVersionForUpdateIfNecessary(entity); - if (update.hasArrayFilters()) { - opts.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList())); - } + Document queryObj = updateContext.getMappedQuery(entity); + UpdateOptions opts = updateContext.getUpdateOptions(entityClass); - Document queryObj = new Document(); + if (updateContext.isAggregationUpdate()) { - if (query != null) { - queryObj.putAll(queryMapper.getMappedObject(query.getQueryObject(), entity)); - } - - if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) { - queryObj.put("$isolated", 1); - } - - if (update instanceof AggregationUpdate) { - - AggregationOperationContext context = entityClass != null - ? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper) - : Aggregation.DEFAULT_CONTEXT; - - List pipeline = new AggregationUtil(queryMapper, mappingContext) - .createPipeline((AggregationUpdate) update, context); + List pipeline = updateContext.getUpdatePipeline(entityClass); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, + update.getUpdateObject(), queryObj); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); return execute(collectionName, collection -> { @@ -1652,43 +1592,29 @@ protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefini serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName); } - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, - entityClass, update.getUpdateObject(), queryObj); - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection; return multi ? collection.updateMany(queryObj, pipeline, opts) : collection.updateOne(queryObj, pipeline, opts); }); } - return execute(collectionName, collection -> { - - operations.forType(entityClass) // - .getCollation(query) // - .map(Collation::toMongoCollation) // - .ifPresent(opts::collation); + Document updateObj = updateContext.getMappedUpdate(entity); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, + updateObj, queryObj); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - Document updateObj = update instanceof MappedUpdate ? update.getUpdateObject() - : updateMapper.getMappedObject(update.getUpdateObject(), entity); + return execute(collectionName, collection -> { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Calling update using query: {} and update: {} in collection: {}", serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName); } - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, - updateObj, queryObj); - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection; if (!UpdateMapper.isUpdateObject(updateObj)) { - ReplaceOptions replaceOptions = new ReplaceOptions(); - replaceOptions.collation(opts.getCollation()); - replaceOptions.upsert(opts.isUpsert()); - + ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass); return collection.replaceOne(queryObj, updateObj, replaceOptions); } else { return multi ? collection.updateMany(queryObj, updateObj, opts) @@ -1697,17 +1623,6 @@ protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefini }); } - private void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity persistentEntity, - UpdateDefinition update) { - - if (persistentEntity != null && persistentEntity.hasVersionProperty()) { - String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName(); - if (!update.modifies(versionFieldName)) { - update.inc(versionFieldName); - } - } - } - @Override public DeleteResult remove(Object object) { @@ -1752,25 +1667,21 @@ protected DeleteResult doRemove(String collectionName, Query query, @Nullabl Assert.hasText(collectionName, "Collection name must not be null or empty!"); MongoPersistentEntity entity = getPersistentEntity(entityClass); - Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), entity); - return execute(collectionName, collection -> { + DeleteContext deleteContext = multi ? queryOperations.deleteQueryContext(query) : queryOperations.deleteSingleContext(query); + Document queryObject = deleteContext.getMappedQuery(entity); + DeleteOptions options = deleteContext.getDeleteOptions(entityClass); - maybeEmitEvent(new BeforeDeleteEvent<>(queryObject, entityClass, collectionName)); - - Document removeQuery = queryObject; + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName, entityClass, + null, queryObject); - DeleteOptions options = new DeleteOptions(); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - operations.forType(entityClass) // - .getCollation(query) // - .map(Collation::toMongoCollation) // - .ifPresent(options::collation); + return execute(collectionName, collection -> { - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName, entityClass, - null, queryObject); + maybeEmitEvent(new BeforeDeleteEvent<>(queryObject, entityClass, collectionName)); - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); + Document removeQuery = queryObject; if (LOGGER.isDebugEnabled()) { LOGGER.debug("Remove using query: {} in collection: {}.", @@ -2479,6 +2390,7 @@ protected T doFindOne(String collectionName, Document query, Document fields Class entityClass) { MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); + Document mappedQuery = queryMapper.getMappedObject(query, entity); Document mappedFields = queryMapper.getMappedObject(fields, entity); @@ -2670,21 +2582,12 @@ protected T doFindAndModify(String collectionName, Document query, Document MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - increaseVersionForUpdateIfNecessary(entity, update); - - Document mappedQuery = queryMapper.getMappedObject(query, entity); - - Object mappedUpdate; - if (update instanceof AggregationUpdate) { + UpdateContext updateContext = queryOperations.updateSingleContext(update, query, false); + updateContext.increaseVersionForUpdateIfNecessary(entity); - AggregationOperationContext context = entityClass != null - ? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper) - : Aggregation.DEFAULT_CONTEXT; - - mappedUpdate = new AggregationUtil(queryMapper, mappingContext).createPipeline((Aggregation) update, context); - } else { - mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity); - } + Document mappedQuery = updateContext.getMappedQuery(entity); + Object mappedUpdate = updateContext.isAggregationUpdate() ? updateContext.getUpdatePipeline(entityClass) + : updateContext.getMappedUpdate(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug( @@ -3286,7 +3189,7 @@ public FindIterable prepare(FindIterable cursor) { String hint = query.getHint(); - if(BsonUtils.isJsonDocument(hint)) { + if (BsonUtils.isJsonDocument(hint)) { cursorToUse = cursorToUse.hint(BsonUtils.parse(hint, mongoDbFactory)); } else { cursorToUse = cursorToUse.hintString(hint); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java new file mode 100644 index 0000000000..a94ad73cd6 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -0,0 +1,661 @@ +/* + * Copyright 2020 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 + * + * https://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 java.util.List; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.bson.BsonValue; +import org.bson.Document; +import org.bson.codecs.Codec; +import org.springframework.data.mapping.PropertyPath; +import org.springframework.data.mapping.PropertyReferenceException; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mongodb.CodecRegistryProvider; +import org.springframework.data.mongodb.core.MappedDocument.MappedUpdate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; +import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; +import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.convert.UpdateMapper; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Collation; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.UpdateDefinition; +import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; +import org.springframework.data.mongodb.util.BsonUtils; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +import com.mongodb.client.model.CountOptions; +import com.mongodb.client.model.DeleteOptions; +import com.mongodb.client.model.ReplaceOptions; +import com.mongodb.client.model.UpdateOptions; + +/** + * {@link QueryOperations} centralizes common operations required before an operation is actually ready to be executed. + * This involves mapping {@link Query queries} into their respective MongoDB representation, computing execution options + * for {@literal count}, {@literal remove}, ...
      + * + * @author Christoph Strobl + * @since 3.0 + */ +class QueryOperations { + + private final QueryMapper queryMapper; + private final UpdateMapper updateMapper; + private final EntityOperations entityOperations; + private final CodecRegistryProvider codecRegistryProvider; + private final MappingContext, MongoPersistentProperty> mappingContext; + private final AggregationUtil aggregationUtil; + + /** + * Create a new instance of {@link QueryOperations}. + * + * @param queryMapper must not be {@literal null}. + * @param updateMapper must not be {@literal null}. + * @param entityOperations must not be {@literal null}. + * @param codecRegistryProvider must not be {@literal null}. + */ + QueryOperations(QueryMapper queryMapper, UpdateMapper updateMapper, EntityOperations entityOperations, + CodecRegistryProvider codecRegistryProvider) { + + this.queryMapper = queryMapper; + this.updateMapper = updateMapper; + this.entityOperations = entityOperations; + this.codecRegistryProvider = codecRegistryProvider; + this.mappingContext = queryMapper.getMappingContext(); + this.aggregationUtil = new AggregationUtil(queryMapper, mappingContext); + } + + /** + * Create a new {@link QueryContext} instance. + * + * @param query must not be {@literal null}. + * @return new instance of {@link QueryContext}. + */ + QueryContext createQueryContext(Query query) { + return new QueryContext(query); + } + + /** + * Create a new {@link DistinctQueryContext} instance. + * + * @param query must not be {@literal null}. + * @return new instance of {@link DistinctQueryContext}. + */ + DistinctQueryContext distincQueryContext(Query query, String fieldName) { + return new DistinctQueryContext(query, fieldName); + } + + /** + * Create a new {@link CountContext} instance. + * + * @param query must not be {@literal null}. + * @return new instance of {@link CountContext}. + */ + CountContext countQueryContext(Query query) { + return new CountContext(query); + } + + /** + * Create a new {@link UpdateContext} instance affecting multiple documents. + * + * @param updateDefinition must not be {@literal null}. + * @param query must not be {@literal null}. + * @param upsert use {@literal true} to insert diff when no existing document found. + * @return new instance of {@link UpdateContext}. + */ + UpdateContext updateContext(UpdateDefinition updateDefinition, Query query, boolean upsert) { + return new UpdateContext(updateDefinition, query, true, upsert); + } + + /** + * Create a new {@link UpdateContext} instance affecting a single document. + * + * @param updateDefinition must not be {@literal null}. + * @param query must not be {@literal null}. + * @param upsert use {@literal true} to insert diff when no existing document found. + * @return new instance of {@link UpdateContext}. + */ + UpdateContext updateSingleContext(UpdateDefinition updateDefinition, Query query, boolean upsert) { + return new UpdateContext(updateDefinition, query, false, upsert); + } + + /** + * Create a new {@link UpdateContext} instance affecting a single document. + * + * @param updateDefinition must not be {@literal null}. + * @param query must not be {@literal null}. + * @param upsert use {@literal true} to insert diff when no existing document found. + * @return new instance of {@link UpdateContext}. + */ + UpdateContext updateSingleContext(UpdateDefinition updateDefinition, Document query, boolean upsert) { + return new UpdateContext(updateDefinition, query, false, upsert); + } + + /** + * Create a new {@link DeleteContext} instance removing all matching documents. + * + * @param query must not be {@literal null}. + * @return new instance of {@link QueryContext}. + */ + DeleteContext deleteQueryContext(Query query) { + return new DeleteContext(query, true); + } + + /** + * Create a new {@link DeleteContext} instance only the first matching document. + * + * @param query must not be {@literal null}. + * @return new instance of {@link QueryContext}. + */ + DeleteContext deleteSingleContext(Query query) { + return new DeleteContext(query, false); + } + + /** + * {@link QueryContext} encapsulates common tasks required to convert a {@link Query} into its MongoDB document + * representation, mapping fieldnames, as well as determinging and applying {@link Collation collations}. + * + * @author Christoph Strobl + */ + class QueryContext { + + private final Query query; + + /** + * Create new a {@link QueryContext} instance from the given {@literal query} (can be eihter a {@link Query} or a + * plain {@link Document}. + * + * @param query can be {@literal null}. + */ + private QueryContext(@Nullable Query query) { + this.query = query != null ? query : new Query(); + } + + /** + * @return never {@literal null}. + */ + Query getQuery() { + return query; + } + + /** + * Extract the raw {@link Query#getQueryObject() unmapped document} from the {@link Query}. + * + * @return + */ + Document getQueryObject() { + return query.getQueryObject(); + } + + /** + * Get the already mapped MongoDB query representation. + * + * @param domainType can be {@literal null}. + * @param entityLookup the {@link Function lookup} used to provide the {@link MongoPersistentEntity} for the + * given{@literal domainType} + * @param + * @return never {@literal null}. + */ + Document getMappedQuery(@Nullable Class domainType, Function, MongoPersistentEntity> entityLookup) { + return getMappedQuery(domainType == null ? null : entityLookup.apply(domainType)); + } + + /** + * Get the already mapped MongoDB query representation. + * + * @param entity the Entity to map field names to. Can be {@literal null}. + * @param + * @return never {@literal null}. + */ + Document getMappedQuery(@Nullable MongoPersistentEntity entity) { + return queryMapper.getMappedObject(getQueryObject(), entity); + } + + /** + * Get the already mapped {@link Query#getFieldsObject() fields projection} + * + * @param entity the Entity to map field names to. Can be {@literal null}. + * @return never {@literal null}. + */ + Document getMappedFields(@Nullable MongoPersistentEntity entity) { + return queryMapper.getMappedFields(query.getFieldsObject(), entity); + } + + /** + * Get the already mapped {@link Query#getSortObject() sort} option. + * + * @param entity the Entity to map field names to. Can be {@literal null}. + * @return never {@literal null}. + */ + Document getMappedSort(@Nullable MongoPersistentEntity entity) { + return queryMapper.getMappedSort(query.getSortObject(), entity); + + } + + /** + * Apply the {@link com.mongodb.client.model.Collation} if present extracted from the {@link Query} or fall back to + * the {@literal domain types} default {@link org.springframework.data.mongodb.core.mapping.Document#collation() + * collation}. + * + * @param domainType can be {@literal null}. + * @param consumer must not be {@literal null}. + */ + void applyCollation(@Nullable Class domainType, Consumer consumer) { + getCollation(domainType).ifPresent(consumer::accept); + } + + /** + * Get the {@link com.mongodb.client.model.Collation} extracted from the {@link Query} if present or fall back to + * the {@literal domain types} default {@link org.springframework.data.mongodb.core.mapping.Document#collation() + * collation}. + * + * @param domainType can be {@literal null}. + * @return never {@literal null}. + */ + Optional getCollation(@Nullable Class domainType) { + + return entityOperations.forType(domainType).getCollation(query) // + .map(Collation::toMongoCollation); + } + } + + /** + * A {@link QueryContext} that encapsulates common tasks required when running {@literal distinct} queries. + * + * @author Christoph Strobl + */ + class DistinctQueryContext extends QueryContext { + + private final String fieldName; + + /** + * Create a new {@link DistinctQueryContext} instance. + * + * @param query can be {@literal null}. + * @param fieldName must not be {@literal null}. + */ + private DistinctQueryContext(@Nullable Object query, String fieldName) { + + super(query instanceof Document ? new BasicQuery((Document) query) : (Query) query); + this.fieldName = fieldName; + } + + @Override + Document getMappedFields(@Nullable MongoPersistentEntity entity) { + return queryMapper.getMappedFields(new Document(fieldName, 1), entity); + } + + /** + * Get the mapped field name to project to. + * + * @param entity can be {@literal null}. + * @return never {@literal null}. + */ + String getMappedFieldName(@Nullable MongoPersistentEntity entity) { + return getMappedFields(entity).keySet().iterator().next(); + } + + /** + * Get the MongoDB native representation of the given {@literal type}. + * + * @param type must not be {@literal null}. + * @param + * @return never {@literal null}. + */ + Class getDriverCompatibleClass(Class type) { + + return codecRegistryProvider.getCodecFor(type) // + .map(Codec::getEncoderClass) // + .orElse((Class) BsonValue.class); + } + + /** + * Get the most speficic read target type based on the user {@literal requestedTargetType} an the property type + * based on meta information extracted from the {@literal domainType}. + * + * @param requestedTargetType must not be {@literal null}. + * @param domainType must not be {@literal null}. + * @return never {@literal null}. + */ + Class getMostSpecificConversionTargetType(Class requestedTargetType, Class domainType) { + + Class conversionTargetType = requestedTargetType; + try { + + Class propertyType = PropertyPath.from(fieldName, domainType).getLeafProperty().getLeafType(); + + // use the more specific type but favor UserType over property one + if (ClassUtils.isAssignable(requestedTargetType, propertyType)) { + conversionTargetType = propertyType; + } + + } catch (PropertyReferenceException e) { + // just don't care about it as we default to Object.class anyway. + } + + return conversionTargetType; + } + } + + /** + * A {@link QueryContext} that encapsulates common tasks required when running {@literal count} queries. + * + * @author Christoph Strobl + */ + class CountContext extends QueryContext { + + /** + * Creates a new {@link CountContext} instance. + * + * @param query can be {@literal null}. + */ + CountContext(@Nullable Query query) { + super(query); + } + + /** + * Get the {@link CountOptions} applicable for the {@link Query}. + * + * @param domainType must not be {@literal null}. + * @return never {@literal null}. + */ + CountOptions getCountOptions(@Nullable Class domainType) { + return getCountOptions(domainType, null); + } + + /** + * Get the {@link CountOptions} applicable for the {@link Query}. + * + * @param domainType can be {@literal null}. + * @param callback a callback to modify the generated options. Can be {@literal null}. + * @return + */ + CountOptions getCountOptions(@Nullable Class domainType, @Nullable Consumer callback) { + + CountOptions options = new CountOptions(); + Query query = getQuery(); + + applyCollation(domainType, options::collation); + + if (query.getLimit() > 0) { + options.limit(query.getLimit()); + } + if (query.getSkip() > 0) { + options.skip((int) query.getSkip()); + } + if (StringUtils.hasText(query.getHint())) { + + String hint = query.getHint(); + if (BsonUtils.isJsonDocument(hint)) { + options.hint(BsonUtils.parse(hint, codecRegistryProvider)); + } else { + options.hintString(hint); + } + } + + if (callback != null) { + callback.accept(options); + } + + return options; + } + } + + /** + * A {@link QueryContext} that encapsulates common tasks required when running {@literal delete} queries. + * + * @author Christoph Strobl + */ + class DeleteContext extends QueryContext { + + private boolean multi; + + /** + * Crate a new {@link DeleteContext} instance. + * + * @param query can be {@literal null}. + * @param multi use {@literal true} to remove all matching documents, {@literal false} for just the first one. + */ + DeleteContext(@Nullable Query query, boolean multi) { + + super(query); + this.multi = multi; + } + + /** + * Get the {@link DeleteOptions} applicable for the {@link Query}. + * + * @param domainType must not be {@literal null}. + * @return never {@literal null}. + */ + DeleteOptions getDeleteOptions(@Nullable Class domainType) { + return getDeleteOptions(domainType, null); + } + + /** + * Get the {@link DeleteOptions} applicable for the {@link Query}. + * + * @param domainType can be {@literal null}. + * @param callback a callback to modify the generated options. Can be {@literal null}. + * @return + */ + DeleteOptions getDeleteOptions(@Nullable Class domainType, @Nullable Consumer callback) { + + DeleteOptions options = new DeleteOptions(); + applyCollation(domainType, options::collation); + + if (callback != null) { + callback.accept(options); + } + + return options; + } + + /** + * @return {@literal true} if all matching documents shall be deleted. + */ + boolean isMulti() { + return multi; + } + } + + /** + * A {@link QueryContext} that encapsulates common tasks required when running {@literal updates}. + */ + class UpdateContext extends QueryContext { + + private final boolean multi; + private final boolean upsert; + private final UpdateDefinition update; + + /** + * Create a new {@link UpdateContext} instance. + * + * @param update must not be {@literal null}. + * @param query must not be {@literal null}. + * @param multi use {@literal true} to update all matching documents. + * @param upsert use {@literal true} to insert a new document if none match. + */ + UpdateContext(UpdateDefinition update, Document query, boolean multi, boolean upsert) { + this(update, new BasicQuery(query), multi, upsert); + } + + /** + * Create a new {@link UpdateContext} instance. + * + * @param update must not be {@literal null}. + * @param query can be {@literal null}. + * @param multi use {@literal true} to update all matching documents. + * @param upsert use {@literal true} to insert a new document if none match. + */ + UpdateContext(UpdateDefinition update, @Nullable Query query, boolean multi, boolean upsert) { + + super(query); + + this.multi = multi; + this.upsert = upsert; + this.update = update; + } + + /** + * Get the {@link UpdateOptions} applicable for the {@link Query}. + * + * @param domainType must not be {@literal null}. + * @return never {@literal null}. + */ + UpdateOptions getUpdateOptions(@Nullable Class domainType) { + return getUpdateOptions(domainType, null); + } + + /** + * Get the {@link UpdateOptions} applicable for the {@link Query}. + * + * @param domainType can be {@literal null}. + * @param callback a callback to modify the generated options. Can be {@literal null}. + * @return + */ + UpdateOptions getUpdateOptions(@Nullable Class domainType, @Nullable Consumer callback) { + + UpdateOptions options = new UpdateOptions(); + options.upsert(upsert); + + if (update.hasArrayFilters()) { + options + .arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList())); + } + + applyCollation(domainType, options::collation); + + if (callback != null) { + callback.accept(options); + } + + return options; + } + + /** + * Get the {@link ReplaceOptions} applicable for the {@link Query}. + * + * @param domainType must not be {@literal null}. + * @return never {@literal null}. + */ + ReplaceOptions getReplaceOptions(@Nullable Class domainType) { + return getReplaceOptions(domainType, null); + } + + /** + * Get the {@link ReplaceOptions} applicable for the {@link Query}. + * + * @param domainType can be {@literal null}. + * @param callback a callback to modify the generated options. Can be {@literal null}. + * @return + */ + ReplaceOptions getReplaceOptions(@Nullable Class domainType, @Nullable Consumer callback) { + + UpdateOptions updateOptions = getUpdateOptions(domainType); + + ReplaceOptions options = new ReplaceOptions(); + options.collation(updateOptions.getCollation()); + options.upsert(updateOptions.isUpsert()); + + if (callback != null) { + callback.accept(options); + } + + return options; + } + + @Override + Document getMappedQuery(@Nullable MongoPersistentEntity domainType) { + + Document mappedQuery = super.getMappedQuery(domainType); + + if (multi && update.isIsolated() && !mappedQuery.containsKey("$isolated")) { + mappedQuery.put("$isolated", 1); + } + + return mappedQuery; + } + + /** + * Get the already mapped aggregation pipeline to use with an {@link #isAggregationUpdate()}. + * + * @param domainType must not be {@literal null}. + * @return never {@literal null}. + */ + List getUpdatePipeline(@Nullable Class domainType) { + + AggregationOperationContext context = domainType != null + ? new RelaxedTypeBasedAggregationOperationContext(domainType, mappingContext, queryMapper) + : Aggregation.DEFAULT_CONTEXT; + + return aggregationUtil.createPipeline((AggregationUpdate) update, context); + } + + /** + * Get the already mapped update {@link Document}. + * + * @param entity + * @return + */ + Document getMappedUpdate(@Nullable MongoPersistentEntity entity) { + + return update instanceof MappedUpdate ? update.getUpdateObject() + : updateMapper.getMappedObject(update.getUpdateObject(), entity); + } + + /** + * Increase a potential {@link MongoPersistentEntity#getVersionProperty() version property} prior to update if not + * already done in the actual {@link UpdateDefinition} + * + * @param persistentEntity can be {@literal null}. + */ + void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity persistentEntity) { + + if (persistentEntity != null && persistentEntity.hasVersionProperty()) { + + String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName(); + if (!update.modifies(versionFieldName)) { + update.inc(versionFieldName); + } + } + } + + /** + * @return {@literal true} if the update holds an aggregation pipeline. + */ + boolean isAggregationUpdate() { + return update instanceof AggregationUpdate; + } + + /** + * @return {@literal true} if all matching documents should be updated. + */ + boolean isMulti() { + return multi; + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 600cceffdd..904e28cf1e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -21,7 +21,6 @@ import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import org.springframework.data.mongodb.util.BsonUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -35,7 +34,6 @@ import org.bson.BsonValue; import org.bson.Document; -import org.bson.codecs.Codec; import org.bson.conversions.Bson; import org.bson.types.ObjectId; import org.reactivestreams.Publisher; @@ -58,8 +56,6 @@ import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.Metric; import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.PropertyPath; -import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.MappingContextEvent; @@ -68,12 +64,15 @@ import org.springframework.data.mongodb.ReactiveMongoDatabaseUtils; import org.springframework.data.mongodb.SessionSynchronization; import org.springframework.data.mongodb.core.EntityOperations.AdaptibleEntity; +import org.springframework.data.mongodb.core.QueryOperations.CountContext; +import org.springframework.data.mongodb.core.QueryOperations.DeleteContext; +import org.springframework.data.mongodb.core.QueryOperations.DistinctQueryContext; +import org.springframework.data.mongodb.core.QueryOperations.QueryContext; +import org.springframework.data.mongodb.core.QueryOperations.UpdateContext; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; -import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext; -import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -112,6 +111,7 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; import org.springframework.data.mongodb.core.validation.Validator; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.util.Optionals; import org.springframework.lang.Nullable; @@ -195,6 +195,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati private final ApplicationListener> indexCreatorListener; private final EntityOperations operations; private final PropertyOperations propertyOperations; + private final QueryOperations queryOperations; private @Nullable WriteConcern writeConcern; private WriteConcernResolver writeConcernResolver = DefaultWriteConcernResolver.INSTANCE; @@ -264,6 +265,7 @@ public ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory, this.mappingContext = this.mongoConverter.getMappingContext(); this.operations = new EntityOperations(this.mappingContext); this.propertyOperations = new PropertyOperations(this.mappingContext); + this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, mongoDatabaseFactory); // We create indexes based on mapping events if (this.mappingContext instanceof MongoMappingContext) { @@ -296,6 +298,7 @@ private ReactiveMongoTemplate(ReactiveMongoDatabaseFactory dbFactory, ReactiveMo this.operations = that.operations; this.propertyOperations = that.propertyOperations; this.sessionSynchronization = that.sessionSynchronization; + this.queryOperations = that.queryOperations; } private void onCheckForIndexes(MongoPersistentEntity entity, Consumer subscriptionExceptionHandler) { @@ -839,7 +842,9 @@ public Mono exists(Query query, @Nullable Class entityClass, String return createFlux(collectionName, collection -> { - Document filter = queryMapper.getMappedObject(query.getQueryObject(), getPersistentEntity(entityClass)); + QueryContext queryContext = queryOperations.createQueryContext(query); + Document filter = queryContext.getMappedQuery(entityClass, this::getPersistentEntity); + FindPublisher findPublisher = collection.find(filter, Document.class) .projection(new Document("_id", 1)); @@ -847,8 +852,7 @@ public Mono exists(Query query, @Nullable Class entityClass, String LOGGER.debug("exists: {} in collection: {}", serializeToJsonSafely(filter), collectionName); } - findPublisher = operations.forType(entityClass).getCollation(query).map(Collation::toMongoCollation) - .map(findPublisher::collation).orElse(findPublisher); + queryContext.applyCollation(entityClass, findPublisher::collation); return findPublisher.limit(1); }).hasElements(); @@ -918,13 +922,11 @@ public Flux findDistinct(Query query, String field, String collectionName Assert.notNull(resultClass, "ResultClass must not be null!"); MongoPersistentEntity entity = getPersistentEntity(entityClass); + DistinctQueryContext distinctQueryContext = queryOperations.distincQueryContext(query, field); - Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), entity); - String mappedFieldName = queryMapper.getMappedFields(new Document(field, 1), entity).keySet().iterator().next(); - - Class mongoDriverCompatibleType = mongoDatabaseFactory.getCodecFor(resultClass) // - .map(Codec::getEncoderClass) // - .orElse((Class) BsonValue.class); + Document mappedQuery = distinctQueryContext.getMappedQuery(entity); + String mappedFieldName = distinctQueryContext.getMappedFieldName(entity); + Class mongoDriverCompatibleType = distinctQueryContext.getDriverCompatibleClass(resultClass); Flux result = execute(collectionName, collection -> { @@ -939,15 +941,13 @@ public Flux findDistinct(Query query, String field, String collectionName } DistinctPublisher publisher = collection.distinct(mappedFieldName, mappedQuery, mongoDriverCompatibleType); - return operations.forType(entityClass).getCollation(query) // - .map(Collation::toMongoCollation) // - .map(publisher::collation) // - .orElse(publisher); + distinctQueryContext.applyCollation(entityClass, publisher::collation); + return publisher; }); if (resultClass == Object.class || mongoDriverCompatibleType != resultClass) { - Class targetType = getMostSpecificConversionTargetType(resultClass, entityClass, field); + Class targetType = distinctQueryContext.getMostSpecificConversionTargetType(resultClass, entityClass); MongoConverter converter = getConverter(); result = result.map(it -> converter.mapValueToTargetType(it, targetType, NO_OP_REF_RESOLVER)); @@ -956,32 +956,6 @@ public Flux findDistinct(Query query, String field, String collectionName return (Flux) result; } - /** - * @param userType must not be {@literal null}. - * @param domainType must not be {@literal null}. - * @param field must not be {@literal null}. - * @return the most specific conversion target type depending on user preference and domain type property. - * @since 2.1 - */ - private static Class getMostSpecificConversionTargetType(Class userType, Class domainType, String field) { - - Class conversionTargetType = userType; - try { - - Class propertyType = PropertyPath.from(field, domainType).getLeafProperty().getLeafType(); - - // use the more specific type but favor UserType over property one - if (ClassUtils.isAssignable(userType, propertyType)) { - conversionTargetType = propertyType; - } - - } catch (PropertyReferenceException e) { - // just don't care about it as we default to Object.class anyway. - } - - return conversionTargetType; - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#aggregate(org.springframework.data.mongodb.core.aggregation.TypedAggregation, java.lang.String, java.lang.Class) @@ -1191,10 +1165,11 @@ public Mono findAndReplace(Query query, S replacement, FindAndReplaceO Assert.isTrue(query.getSkip() <= 0, "Query must not define skip."); MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityType); + QueryContext queryContext = queryOperations.createQueryContext(query); - Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), entity); - Document mappedFields = queryMapper.getMappedFields(query.getFieldsObject(), entity); - Document mappedSort = queryMapper.getMappedSort(query.getSortObject(), entity); + Document mappedQuery = queryContext.getMappedQuery(entity); + Document mappedFields = queryContext.getMappedFields(entity); + Document mappedSort = queryContext.getMappedSort(entity); return Mono.just(PersistableEntityModel.of(replacement, collectionName)) // .doOnNext(it -> maybeEmitEvent(new BeforeConvertEvent<>(it.getSource(), it.getCollection()))) // @@ -1212,8 +1187,8 @@ public Mono findAndReplace(Query query, S replacement, FindAndReplaceO PersistableEntityModel flowObject = (PersistableEntityModel) it; return doFindAndReplace(flowObject.getCollection(), mappedQuery, mappedFields, mappedSort, - operations.forType(entityType).getCollation(query).map(Collation::toMongoCollation).orElse(null), - entityType, flowObject.getTarget(), options, resultType); + queryContext.getCollation(entityType).orElse(null), entityType, flowObject.getTarget(), options, + resultType); }); } @@ -1267,30 +1242,10 @@ public Mono count(Query query, @Nullable Class entityClass, String coll return createMono(collectionName, collection -> { - Document filter = queryMapper.getMappedObject(query.getQueryObject(), - entityClass == null ? null : mappingContext.getPersistentEntity(entityClass)); - - CountOptions options = new CountOptions(); - query.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation); - - if (query.getLimit() > 0) { - options.limit(query.getLimit()); - } - if (query.getSkip() > 0) { - options.skip((int) query.getSkip()); - } - if (StringUtils.hasText(query.getHint())) { - - String hint = query.getHint(); - if(BsonUtils.isJsonDocument(hint)) { - options = options.hint(BsonUtils.parse(hint, mongoDatabaseFactory)); - } else { - options = options.hintString(hint); - } - } + CountContext countContext = queryOperations.countQueryContext(query); - operations.forType(entityClass).getCollation(query).map(Collation::toMongoCollation) // - .ifPresent(options::collation); + CountOptions options = countContext.getCountOptions(entityClass); + Document filter = countContext.getMappedQuery(entityClass, mappingContext::getPersistentEntity); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Executing count: {} in collection: {}", serializeToJsonSafely(filter), collectionName); @@ -1775,35 +1730,22 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla } MongoPersistentEntity entity = entityClass == null ? null : getPersistentEntity(entityClass); - increaseVersionForUpdateIfNecessary(entity, update); - Document queryObj = queryMapper.getMappedObject(query.getQueryObject(), entity); + UpdateContext updateContext = multi ? queryOperations.updateContext(update, query, upsert) + : queryOperations.updateSingleContext(update, query, upsert); + updateContext.increaseVersionForUpdateIfNecessary(entity); - UpdateOptions updateOptions = new UpdateOptions().upsert(upsert); - operations.forType(entityClass).getCollation(query) // - .map(Collation::toMongoCollation) // - .ifPresent(updateOptions::collation); - - if (update.hasArrayFilters()) { - - updateOptions.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument) - .map(it -> queryMapper.getMappedObject(it, entity)).collect(Collectors.toList())); - } - - if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) { - queryObj.put("$isolated", 1); - } + Document queryObj = updateContext.getMappedQuery(entity); + UpdateOptions updateOptions = updateContext.getUpdateOptions(entityClass); Flux result; - if (update instanceof AggregationUpdate) { + if (updateContext.isAggregationUpdate()) { - AggregationOperationContext context = entityClass != null - ? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper) - : Aggregation.DEFAULT_CONTEXT; - - List pipeline = new AggregationUtil(queryMapper, mappingContext) - .createPipeline((AggregationUpdate) update, context); + List pipeline = updateContext.getUpdatePipeline(entityClass); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, + update.getUpdateObject(), queryObj); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); result = execute(collectionName, collection -> { @@ -1812,10 +1754,6 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName)); } - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, - entityClass, update.getUpdateObject(), queryObj); - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection; return multi ? collection.updateMany(queryObj, pipeline, updateOptions) @@ -1823,26 +1761,23 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla }); } else { - result = execute(collectionName, collection -> { + Document updateObj = updateContext.getMappedUpdate(entity); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, + updateObj, queryObj); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - Document updateObj = updateMapper.getMappedObject(update.getUpdateObject(), entity); + result = execute(collectionName, collection -> { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s", serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName)); } - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, - entityClass, updateObj, queryObj); - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); MongoCollection collectionToUse = prepareCollection(collection, writeConcernToUse); if (!UpdateMapper.isUpdateObject(updateObj)) { - ReplaceOptions replaceOptions = new ReplaceOptions(); - replaceOptions.upsert(updateOptions.isUpsert()); - replaceOptions.collation(updateOptions.getCollation()); - + ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass); return collectionToUse.replaceOne(queryObj, updateObj, replaceOptions); } @@ -1856,7 +1791,7 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla if (entity != null && entity.hasVersionProperty() && !multi) { if (updateResult.wasAcknowledged() && updateResult.getMatchedCount() == 0) { - Document updateObj = updateMapper.getMappedObject(update.getUpdateObject(), entity); + Document updateObj = updateContext.getMappedUpdate(entity); if (containsVersionProperty(queryObj, entity)) throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: " + updateObj.toString() + " to collection " + collectionName); @@ -1867,17 +1802,6 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla return result.next(); } - private void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity persistentEntity, - UpdateDefinition update) { - - if (persistentEntity != null && persistentEntity.hasVersionProperty()) { - String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName(); - if (!update.modifies(versionFieldName)) { - update.inc(versionFieldName); - } - } - } - private boolean containsVersionProperty(Document document, @Nullable MongoPersistentEntity persistentEntity) { if (persistentEntity == null || !persistentEntity.hasVersionProperty()) { @@ -1981,24 +1905,20 @@ protected Mono doRemove(String collectionName, Query query, @N Assert.hasText(collectionName, "Collection name must not be null or empty!"); - Document queryObject = query.getQueryObject(); MongoPersistentEntity entity = getPersistentEntity(entityClass); - Document removeQuery = queryMapper.getMappedObject(queryObject, entity); + + DeleteContext deleteContext = queryOperations.deleteQueryContext(query); + Document queryObject = deleteContext.getMappedQuery(entity); + DeleteOptions deleteOptions = deleteContext.getDeleteOptions(entityClass); + Document removeQuery = deleteContext.getMappedQuery(entity); + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName, entityClass, + null, removeQuery); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); return execute(collectionName, collection -> { maybeEmitEvent(new BeforeDeleteEvent<>(removeQuery, entityClass, collectionName)); - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName, entityClass, - null, removeQuery); - - DeleteOptions deleteOptions = new DeleteOptions(); - - operations.forType(entityClass).getCollation(query) // - .map(Collation::toMongoCollation) // - .ifPresent(deleteOptions::collation); - - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); MongoCollection collectionToUse = prepareCollection(collection, writeConcernToUse); if (LOGGER.isDebugEnabled()) { @@ -2586,22 +2506,14 @@ protected Mono doFindAndModify(String collectionName, Document query, Doc Class entityClass, UpdateDefinition update, FindAndModifyOptions options) { MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - increaseVersionForUpdateIfNecessary(entity, update); + UpdateContext updateContext = queryOperations.updateSingleContext(update, query, false); + updateContext.increaseVersionForUpdateIfNecessary(entity); return Mono.defer(() -> { - Document mappedQuery = queryMapper.getMappedObject(query, entity); - - Object mappedUpdate; - if (update instanceof AggregationUpdate) { - - AggregationOperationContext context = new RelaxedTypeBasedAggregationOperationContext(entityClass, - mappingContext, queryMapper); - - mappedUpdate = new AggregationUtil(queryMapper, mappingContext).createPipeline((Aggregation) update, context); - } else { - mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity); - } + Document mappedQuery = updateContext.getMappedQuery(entity); + Object mappedUpdate = updateContext.isAggregationUpdate() ? updateContext.getUpdatePipeline(entityClass) + : updateContext.getMappedUpdate(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format( @@ -3286,7 +3198,7 @@ public FindPublisher prepare(FindPublisher findPublisher) { String hint = query.getHint(); - if(BsonUtils.isJsonDocument(hint)) { + if (BsonUtils.isJsonDocument(hint)) { findPublisherToUse = findPublisherToUse.hint(BsonUtils.parse(hint, mongoDatabaseFactory)); } else { findPublisherToUse = findPublisherToUse.hintString(hint); From f8ee9648da1d976f3de18916ff0fca3e8ad10b84 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 29 Jan 2020 13:40:01 +0100 Subject: [PATCH 0061/1381] DATAMONGO-2365 - Polishing. Reformat code. Fix method name and generics. Whitespaces. Original pull request: #828. --- .../data/mongodb/core/MongoTemplate.java | 10 ++++--- .../data/mongodb/core/QueryOperations.java | 28 ++++++++++--------- .../mongodb/core/ReactiveMongoTemplate.java | 17 ++++++----- 3 files changed, 29 insertions(+), 26 deletions(-) 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 743724a644..96b2d4620c 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 @@ -17,7 +17,6 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; -import com.mongodb.client.MongoClient; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NonNull; @@ -34,6 +33,7 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -54,8 +54,8 @@ import org.springframework.data.geo.Metric; import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.mongodb.MongoDatabaseUtils; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.MongoDatabaseUtils; import org.springframework.data.mongodb.SessionSynchronization; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; @@ -134,6 +134,7 @@ import com.mongodb.client.DistinctIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MapReduceIterable; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; @@ -904,7 +905,7 @@ public List findDistinct(Query query, String field, String collectionName Assert.notNull(resultClass, "ResultClass must not be null!"); MongoPersistentEntity entity = entityClass != Object.class ? getPersistentEntity(entityClass) : null; - DistinctQueryContext distinctQueryContext = queryOperations.distincQueryContext(query, field); + DistinctQueryContext distinctQueryContext = queryOperations.distinctQueryContext(query, field); Document mappedQuery = distinctQueryContext.getMappedQuery(entity); String mappedFieldName = distinctQueryContext.getMappedFieldName(entity); @@ -1668,7 +1669,8 @@ protected DeleteResult doRemove(String collectionName, Query query, @Nullabl MongoPersistentEntity entity = getPersistentEntity(entityClass); - DeleteContext deleteContext = multi ? queryOperations.deleteQueryContext(query) : queryOperations.deleteSingleContext(query); + DeleteContext deleteContext = multi ? queryOperations.deleteQueryContext(query) + : queryOperations.deleteSingleContext(query); Document queryObject = deleteContext.getMappedQuery(entity); DeleteOptions options = deleteContext.getDeleteOptions(entityClass); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index a94ad73cd6..23c88f5600 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -56,7 +56,7 @@ * {@link QueryOperations} centralizes common operations required before an operation is actually ready to be executed. * This involves mapping {@link Query queries} into their respective MongoDB representation, computing execution options * for {@literal count}, {@literal remove}, ...
      - * + * * @author Christoph Strobl * @since 3.0 */ @@ -104,7 +104,7 @@ QueryContext createQueryContext(Query query) { * @param query must not be {@literal null}. * @return new instance of {@link DistinctQueryContext}. */ - DistinctQueryContext distincQueryContext(Query query, String fieldName) { + DistinctQueryContext distinctQueryContext(Query query, String fieldName) { return new DistinctQueryContext(query, fieldName); } @@ -203,7 +203,7 @@ Query getQuery() { /** * Extract the raw {@link Query#getQueryObject() unmapped document} from the {@link Query}. - * + * * @return */ Document getQueryObject() { @@ -212,20 +212,21 @@ Document getQueryObject() { /** * Get the already mapped MongoDB query representation. - * + * * @param domainType can be {@literal null}. * @param entityLookup the {@link Function lookup} used to provide the {@link MongoPersistentEntity} for the * given{@literal domainType} * @param * @return never {@literal null}. */ - Document getMappedQuery(@Nullable Class domainType, Function, MongoPersistentEntity> entityLookup) { + Document getMappedQuery(@Nullable Class domainType, + Function, MongoPersistentEntity> entityLookup) { return getMappedQuery(domainType == null ? null : entityLookup.apply(domainType)); } /** * Get the already mapped MongoDB query representation. - * + * * @param entity the Entity to map field names to. Can be {@literal null}. * @param * @return never {@literal null}. @@ -259,7 +260,7 @@ Document getMappedSort(@Nullable MongoPersistentEntity entity) { * Apply the {@link com.mongodb.client.model.Collation} if present extracted from the {@link Query} or fall back to * the {@literal domain types} default {@link org.springframework.data.mongodb.core.mapping.Document#collation() * collation}. - * + * * @param domainType can be {@literal null}. * @param consumer must not be {@literal null}. */ @@ -271,7 +272,7 @@ void applyCollation(@Nullable Class domainType, Consumer getCollation(@Nullable Class dom /** * A {@link QueryContext} that encapsulates common tasks required when running {@literal distinct} queries. - * + * * @author Christoph Strobl */ class DistinctQueryContext extends QueryContext { @@ -325,6 +326,7 @@ String getMappedFieldName(@Nullable MongoPersistentEntity entity) { * @param * @return never {@literal null}. */ + @SuppressWarnings("unchecked") Class getDriverCompatibleClass(Class type) { return codecRegistryProvider.getCodecFor(type) // @@ -369,7 +371,7 @@ class CountContext extends QueryContext { /** * Creates a new {@link CountContext} instance. - * + * * @param query can be {@literal null}. */ CountContext(@Nullable Query query) { @@ -431,7 +433,7 @@ CountOptions getCountOptions(@Nullable Class domainType, @Nullable Consumer Document getMappedQuery(@Nullable MongoPersistentEntity domainType) { /** * Get the already mapped aggregation pipeline to use with an {@link #isAggregationUpdate()}. - * + * * @param domainType must not be {@literal null}. * @return never {@literal null}. */ @@ -630,7 +632,7 @@ Document getMappedUpdate(@Nullable MongoPersistentEntity entity) { /** * Increase a potential {@link MongoPersistentEntity#getVersionProperty() version property} prior to update if not * already done in the actual {@link UpdateDefinition} - * + * * @param persistentEntity can be {@literal null}. */ void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity persistentEntity) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 904e28cf1e..63413b77bc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,7 +17,6 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; -import com.mongodb.client.result.InsertOneResult; import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -40,6 +39,7 @@ import org.reactivestreams.Subscriber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -140,6 +140,7 @@ import com.mongodb.client.model.ValidationOptions; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.result.DeleteResult; +import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; import com.mongodb.reactivestreams.client.AggregatePublisher; import com.mongodb.reactivestreams.client.ChangeStreamPublisher; @@ -922,7 +923,7 @@ public Flux findDistinct(Query query, String field, String collectionName Assert.notNull(resultClass, "ResultClass must not be null!"); MongoPersistentEntity entity = getPersistentEntity(entityClass); - DistinctQueryContext distinctQueryContext = queryOperations.distincQueryContext(query, field); + DistinctQueryContext distinctQueryContext = queryOperations.distinctQueryContext(query, field); Document mappedQuery = distinctQueryContext.getMappedQuery(entity); String mappedFieldName = distinctQueryContext.getMappedFieldName(entity); @@ -2284,12 +2285,10 @@ protected Mono> doCreateCollection(String collectionNa return createMono(db -> db.createCollection(collectionName, collectionOptions)).doOnSuccess(it -> { - - // TODO: Emit a collection created event - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Created collection [{}]", collectionName); - } - + // TODO: Emit a collection created event + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Created collection [{}]", collectionName); + } }).thenReturn(getCollection(collectionName)); } @@ -2934,7 +2933,7 @@ private static FindOneAndUpdateOptions convertToFindOneAndUpdateOptions(FindAndM result = options.getCollation().map(Collation::toMongoCollation).map(result::collation).orElse(result); - if(!CollectionUtils.isEmpty(arrayFilters)) { + if (!CollectionUtils.isEmpty(arrayFilters)) { result.arrayFilters(arrayFilters); } From 85519eb84d5a42b5478d99483d5ac158fd1202b5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 7 Jan 2020 09:01:24 +0100 Subject: [PATCH 0062/1381] DATAMONGO-2449 - Evaluate allowDiskUse added to Meta annotation when executing derived Aggregation. @Meta(allowDiskUse...) allows to set the according aggregation option when executing a String based annotation via a repository definition. Original pull request: #827. --- .../data/mongodb/core/query/Meta.java | 23 ++++++++++++++ .../data/mongodb/repository/Meta.java | 9 ++++++ .../repository/query/AggregationUtils.java | 9 ++++++ .../repository/query/MongoQueryMethod.java | 4 +++ .../StringBasedAggregationUnitTests.java | 13 +++++--- .../mongo-repositories-aggregation.adoc | 31 ++++++++++++++++++- 6 files changed, 83 insertions(+), 6 deletions(-) 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 1addc323e8..95d3dc1671 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 @@ -52,6 +52,7 @@ private enum MetaKey { private final Map values = new LinkedHashMap<>(2); private final Set flags = new LinkedHashSet<>(); private Integer cursorBatchSize; + private Boolean allowDiskUse; public Meta() {} @@ -65,6 +66,7 @@ public Meta() {} this.values.putAll(source.values); this.flags.addAll(source.flags); this.cursorBatchSize = source.cursorBatchSize; + this.allowDiskUse = source.allowDiskUse; } /** @@ -245,6 +247,27 @@ public boolean equals(Object obj) { return ObjectUtils.nullSafeEquals(this.flags, other.flags); } + /** + * When set to true, aggregation stages can write data to disk. + * + * @return {@literal null} if not set. + * @since 3.0 + */ + @Nullable + public Boolean getAllowDiskUse() { + return allowDiskUse; + } + + /** + * Set to true, to allow aggregation stages to write data to disk. + * + * @param allowDiskUse use {@literal null} for server defaults. + * @since 3.0 + */ + public void setAllowDiskUse(@Nullable Boolean allowDiskUse) { + this.allowDiskUse = allowDiskUse; + } + /** * {@link CursorOption} represents {@code OP_QUERY} wire protocol flags to change the behavior of queries. * 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 0d6454b88c..64159605ec 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 @@ -67,4 +67,13 @@ */ org.springframework.data.mongodb.core.query.Meta.CursorOption[] flags() default {}; + /** + * When set to true, aggregation stages can write data to disk. + * + * @return {@literal false} by default. + * @since 3.0 + * @see Aggregation + */ + boolean allowDiskUse() default false; + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index a514d3a2d9..d780d43c17 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -17,6 +17,7 @@ import lombok.experimental.UtilityClass; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -93,6 +94,14 @@ static AggregationOptions.Builder applyMeta(AggregationOptions.Builder builder, builder.cursorBatchSize(meta.getCursorBatchSize()); } + if(meta.getMaxTimeMsec() != null && meta.getMaxTimeMsec() > 0) { + builder.maxTime(Duration.ofMillis(meta.getMaxTimeMsec())); + } + + if (meta.getAllowDiskUse() != null) { + builder.allowDiskUse(meta.getAllowDiskUse()); + } + return builder; } 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 05d864a17d..d97a846322 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 @@ -293,6 +293,10 @@ public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes() } } + if(meta.allowDiskUse()) { + metaAttributes.setAllowDiskUse(meta.allowDiskUse()); + } + return metaAttributes; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java index e77e7e77bf..f1ba24abaf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java @@ -22,6 +22,7 @@ import lombok.Value; import java.lang.reflect.Method; +import java.time.Duration; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -33,7 +34,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; - import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoOperations; @@ -102,18 +102,19 @@ public void plainStringAggregation() { assertThat(pipelineOf(invocation)).containsExactly(GROUP_BY_LASTNAME, SORT); } - @Test // DATAMONGO-2153 + @Test // DATAMONGO-2153, DATAMONGO-2449 public void plainStringAggregationConsidersMeta() { AggregationInvocation invocation = executeAggregation("plainStringAggregation"); - AggregationOptions options = invocation.aggregation.getOptions(); assertThat(options.getComment()).contains("expensive-aggregation"); assertThat(options.getCursorBatchSize()).isEqualTo(42); + assertThat(options.isAllowDiskUse()).isTrue(); + assertThat(options.getMaxTime()).isEqualTo(Duration.ofMillis(100)); } - @Test // DATAMONGO-2153 + @Test // DATAMONGO-2153, DATAMONGO-2449 public void returnSingleObject() { PersonAggregate expected = new PersonAggregate(); @@ -126,6 +127,8 @@ public void returnSingleObject() { assertThat(options.getComment()).isEmpty(); assertThat(options.getCursorBatchSize()).isNull(); + assertThat(options.isAllowDiskUse()).isFalse(); + assertThat(options.getMaxTime()).isEqualTo(Duration.ZERO); } @Test // DATAMONGO-2153 @@ -246,7 +249,7 @@ private Class targetTypeOf(AggregationInvocation invocation) { private interface SampleRepository extends Repository { - @Meta(cursorBatchSize = 42, comment = "expensive-aggregation") + @Meta(cursorBatchSize = 42, comment = "expensive-aggregation", allowDiskUse = true, maxExecutionTimeMs = 100) @Aggregation({ RAW_GROUP_BY_LASTNAME_STRING, RAW_SORT_STRING }) PersonAggregate plainStringAggregation(); diff --git a/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc b/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc index feba576ad2..2372aaedec 100644 --- a/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc +++ b/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc @@ -11,7 +11,6 @@ The definition may contain simple placeholders like `?0` as well as https://docs ---- public interface PersonRepository extends CrudReppsitory { - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") List groupByLastnameAndFirstnames(); <1> @@ -74,6 +73,36 @@ To gain more control, you might consider `AggregationResult` as method return ty <8> Like in <6>, a single value can be directly obtained from multiple result ``Document``s. ==== +In some scenarios aggregations might require additional options like a maximum execution time, additional log comments or the permission to temporarily write data to disk. +Use the `@Meta` annotation to set those options via `maxExecutionTimeMs`, `comment` or `allowDiskUse`. + +[source,java] +---- +public interface PersonRepository extends CrudReppsitory { + + @Meta(allowDiskUse = true) + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + List groupByLastnameAndFirstnames(); +} +---- + +Or use `@Meta` to create your own annotation as shown in the sample below. + +[source,java] +---- +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +@Meta(allowDiskUse = true) +@interface AllowDiskUse { } + +public interface PersonRepository extends CrudReppsitory { + + @AllowDiskUse + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + List groupByLastnameAndFirstnames(); +} +---- + TIP: You can use `@Aggregation` also with <>. [NOTE] From 46806a5606edde68781c8b1aabe426a9a8b674ff Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 3 Feb 2020 11:00:30 +0100 Subject: [PATCH 0063/1381] DATAMONGO-2449 - Polishing. Reformat code. Tweak Javadoc. Original pull request: #827. --- .../data/mongodb/core/query/Meta.java | 44 +++++++++---------- .../data/mongodb/repository/Meta.java | 4 +- .../repository/query/AggregationUtils.java | 2 +- .../repository/query/MongoQueryMethod.java | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) 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 95d3dc1671..a32435c5d0 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 @@ -169,11 +169,32 @@ public Set getFlags() { return flags; } + /** + * When set to {@literal true}, aggregation stages can write data to disk. + * + * @return {@literal null} if not set. + * @since 3.0 + */ + @Nullable + public Boolean getAllowDiskUse() { + return allowDiskUse; + } + + /** + * Set to {@literal true}, to allow aggregation stages to write data to disk. + * + * @param allowDiskUse use {@literal null} for server defaults. + * @since 3.0 + */ + public void setAllowDiskUse(@Nullable Boolean allowDiskUse) { + this.allowDiskUse = allowDiskUse; + } + /** * @return */ public boolean hasValues() { - return !this.values.isEmpty() || !this.flags.isEmpty() || this.cursorBatchSize != null; + return !this.values.isEmpty() || !this.flags.isEmpty() || this.cursorBatchSize != null || this.allowDiskUse != null; } /** @@ -247,27 +268,6 @@ public boolean equals(Object obj) { return ObjectUtils.nullSafeEquals(this.flags, other.flags); } - /** - * When set to true, aggregation stages can write data to disk. - * - * @return {@literal null} if not set. - * @since 3.0 - */ - @Nullable - public Boolean getAllowDiskUse() { - return allowDiskUse; - } - - /** - * Set to true, to allow aggregation stages to write data to disk. - * - * @param allowDiskUse use {@literal null} for server defaults. - * @since 3.0 - */ - public void setAllowDiskUse(@Nullable Boolean allowDiskUse) { - this.allowDiskUse = allowDiskUse; - } - /** * {@link CursorOption} represents {@code OP_QUERY} wire protocol flags to change the behavior of queries. * 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 64159605ec..929e3a63eb 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 @@ -46,7 +46,7 @@ * Sets the number of documents to return per batch.
      * Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single * batch indicating to the server that the client will not ask for a subsequent one. - * + * * @return {@literal 0 (zero)} by default. * @since 2.1 */ @@ -68,7 +68,7 @@ org.springframework.data.mongodb.core.query.Meta.CursorOption[] flags() default {}; /** - * When set to true, aggregation stages can write data to disk. + * When set to {@literal true}, aggregation stages can write data to disk. * * @return {@literal false} by default. * @since 3.0 diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index d780d43c17..e78cb6504a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -94,7 +94,7 @@ static AggregationOptions.Builder applyMeta(AggregationOptions.Builder builder, builder.cursorBatchSize(meta.getCursorBatchSize()); } - if(meta.getMaxTimeMsec() != null && meta.getMaxTimeMsec() > 0) { + if (meta.getMaxTimeMsec() != null && meta.getMaxTimeMsec() > 0) { builder.maxTime(Duration.ofMillis(meta.getMaxTimeMsec())); } 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 d97a846322..a2ec157f19 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 @@ -293,7 +293,7 @@ public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes() } } - if(meta.allowDiskUse()) { + if (meta.allowDiskUse()) { metaAttributes.setAllowDiskUse(meta.allowDiskUse()); } From 291d84591cd982394b3cb6d5fc453dd4691dd314 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 28 Jan 2020 08:59:50 +0100 Subject: [PATCH 0064/1381] DATAMONGO-2460 - Fix target type computation for complex id properties with @Field annotation. We now set the target type to org.bson.Document for id properties annotated with @Field having the implicit target type derived from the annotation. Along the lines we fixed warn message when an id property with explicit (unsupported) field name is detected. Original pull request: #830. --- .../mapping/BasicMongoPersistentProperty.java | 15 ++++++++++++-- ...BasicMongoPersistentPropertyUnitTests.java | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 1bb0cf83a9..f0caf4e7d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -79,8 +79,14 @@ public BasicMongoPersistentProperty(Property property, MongoPersistentEntity this.fieldNamingStrategy = fieldNamingStrategy == null ? PropertyNameFieldNamingStrategy.INSTANCE : fieldNamingStrategy; - if (isIdProperty() && getFieldName() != ID_FIELD_NAME) { - LOG.warn("Customizing field name for id property not allowed! Custom name will not be considered!"); + if (isIdProperty() && hasExplicitFieldName()) { + + String annotatedName = getAnnotatedFieldName(); + if (!ID_FIELD_NAME.equals(annotatedName)) { + LOG.warn( + "Customizing field name for id property '{}.{}' is not allowed! Custom name ('{}') will not be considered!", + owner.getName(), getName(), annotatedName); + } } } @@ -167,6 +173,11 @@ public Class getFieldType() { FieldType fieldType = fieldAnnotation.targetType(); if (fieldType == FieldType.IMPLICIT) { + + if (isEntity()) { + return org.bson.Document.class; + } + return getType(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 5e9d6868cd..3e0671f044 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Locale; +import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; @@ -223,6 +224,13 @@ public void fieldTypeShouldBeObjectIdForPropertiesAnnotatedWithMongoIdAndTargetT assertThat(property.getFieldType()).isEqualTo(ObjectId.class); } + @Test // DATAMONGO-2460 + public void fieldTypeShouldBeDocumentForPropertiesAnnotatedIdWhenAComplexTypeAndFieldTypeImplicit() { + + MongoPersistentProperty property = getPropertyFor(WithComplexId.class, "id"); + assertThat(property.getFieldType()).isEqualTo(Document.class); + } + private MongoPersistentProperty getPropertyFor(Field field) { return getPropertyFor(entity, field); } @@ -329,4 +337,16 @@ static class WithStringMongoIdMappedToObjectId { @MongoId(FieldType.OBJECT_ID) String id; } + + static class ComplexId { + + String value; + } + + static class WithComplexId { + + @Id + @org.springframework.data.mongodb.core.mapping.Field + ComplexId id; + } } From 073668b1d16221242bba73fd1bd0e35ee2066f05 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 3 Feb 2020 11:25:01 +0100 Subject: [PATCH 0065/1381] DATAMONGO-2460 - Polishing. Reformat code. Use diamond syntax. Original pull request: #830. --- .../mapping/BasicMongoPersistentPropertyUnitTests.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 3e0671f044..6baaa7899a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -55,7 +55,7 @@ public class BasicMongoPersistentPropertyUnitTests { @Before public void setup() { - entity = new BasicMongoPersistentEntity(ClassTypeInformation.from(Person.class)); + entity = new BasicMongoPersistentEntity<>(ClassTypeInformation.from(Person.class)); } @Test @@ -236,7 +236,7 @@ private MongoPersistentProperty getPropertyFor(Field field) { } private static MongoPersistentProperty getPropertyFor(Class type, String fieldname) { - return getPropertyFor(new BasicMongoPersistentEntity(ClassTypeInformation.from(type)), fieldname); + return getPropertyFor(new BasicMongoPersistentEntity<>(ClassTypeInformation.from(type)), fieldname); } private static MongoPersistentProperty getPropertyFor(MongoPersistentEntity entity, String fieldname) { @@ -345,8 +345,6 @@ static class ComplexId { static class WithComplexId { - @Id - @org.springframework.data.mongodb.core.mapping.Field - ComplexId id; + @Id @org.springframework.data.mongodb.core.mapping.Field ComplexId id; } } From f69ddb6c61d68b522a8af59fce36d314ddbc6113 Mon Sep 17 00:00:00 2001 From: LiangYong <517219382@qq.com> Date: Sun, 15 Dec 2019 18:22:47 +0800 Subject: [PATCH 0066/1381] DATAMONGO-2464 - Fix code examples in reference documentation. fixed repository miss "{" issue. Original pull request: #816. --- src/main/asciidoc/reference/mongo-repositories.adoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index 04715cb299..f1fc60af1a 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -328,7 +328,7 @@ The following example shows how to define a `near` query that finds all persons ==== [source,java] ---- -public interface PersonRepository extends MongoRepository +public interface PersonRepository extends MongoRepository { // { 'location' : { '$near' : [point.x, point.y], '$maxDistance' : distance}} List findByLocationNear(Point location, Distance distance); @@ -361,7 +361,7 @@ Spring Data MongoDb supports geo-near queries, as the following example shows: [source,java] ---- -public interface PersonRepository extends MongoRepository +public interface PersonRepository extends MongoRepository { // {'geoNear' : 'location', 'near' : [x, y] } GeoResults findByLocationNear(Point location); @@ -388,7 +388,7 @@ By adding the `org.springframework.data.mongodb.repository.Query` annotation to [source,java] ---- -public interface PersonRepository extends MongoRepository +public interface PersonRepository extends MongoRepository { @Query("{ 'firstname' : ?0 }") List findByThePersonsFirstname(String firstname); @@ -404,7 +404,7 @@ You can also use the filter property to restrict the set of properties that is m [source,java] ---- -public interface PersonRepository extends MongoRepository +public interface PersonRepository extends MongoRepository { @Query(value="{ 'firstname' : ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}") List findByThePersonsFirstname(String firstname); @@ -455,7 +455,7 @@ to declare the predicate value for `lastname` (which is equivalent to the `?0` p [source,java] ---- -public interface PersonRepository extends MongoRepository +public interface PersonRepository extends MongoRepository { @Query("{'lastname': ?#{[0]} }") List findByQueryWithExpression(String param0); @@ -467,7 +467,7 @@ used in conjunction with JSON reveal a side-effect, because Map-like declaration [source,java] ---- -public interface PersonRepository extends MongoRepository +public interface PersonRepository extends MongoRepository { @Query("{'id': ?#{ [0] ? {$exists :true} : [1] }}") List findByQueryWithExpressionAndNestedObject(boolean param0, String param1); From d0c2c820d712a98d77ca03641afaff50150bbb44 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 3 Feb 2020 11:33:42 +0100 Subject: [PATCH 0067/1381] DATAMONGO-2464 - Polishing. Apply fix also to reactive MongoDB repository documentation. Original pull request: #816. --- src/main/asciidoc/reference/reactive-mongo-repositories.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc index 9866878870..c9c54cc807 100644 --- a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc +++ b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc @@ -160,7 +160,7 @@ The following example shows how to define a `near` query that finds all persons ==== [source,java] ---- -public interface PersonRepository extends ReactiveMongoRepository +public interface PersonRepository extends ReactiveMongoRepository { // { 'location' : { '$near' : [point.x, point.y], '$maxDistance' : distance}} Flux findByLocationNear(Point location, Distance distance); @@ -195,7 +195,7 @@ Spring Data MongoDB supports geo-near queries, as the following example shows: [source,java] ---- -public interface PersonRepository extends ReactiveMongoRepository +public interface PersonRepository extends ReactiveMongoRepository { // {'geoNear' : 'location', 'near' : [x, y] } Flux> findByLocationNear(Point location); From 2c9956723e3994a5981c2e6f617d860139ceb78c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 22 Nov 2019 12:16:52 +0100 Subject: [PATCH 0068/1381] DATAMONGO-2417 - Typesafe Kotlin Extension for distinct queries. We now provide extensions for imperative and reactive distinct queries accepting Kotlin's KProperty and KProperty1 to express type-safe queries: mongo.query().distinct(Customer::name) mongo.distinct(Customer::name) Original Pull Request: #809 --- .../core/ExecutableFindOperationExtensions.kt | 21 +++++++++++++++ .../core/ReactiveFindOperationExtensions.kt | 21 +++++++++++++++ .../ExecutableFindOperationExtensionsTests.kt | 26 +++++++++++++++++++ .../ReactiveFindOperationExtensionsTests.kt | 25 ++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt index e4a88c79cb..15a5c18076 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt @@ -15,7 +15,10 @@ */ package org.springframework.data.mongodb.core +import org.springframework.data.mongodb.core.query.asString import kotlin.reflect.KClass +import kotlin.reflect.KProperty +import kotlin.reflect.KProperty1 /** * Extension for [ExecutableFindOperation.query] providing a [KClass] based variant. @@ -38,6 +41,15 @@ fun ExecutableFindOperation.query(entityClass: KClass): ExecutableF inline fun ExecutableFindOperation.query(): ExecutableFindOperation.ExecutableFind = query(T::class.java) +/** + * Extension for [ExecutableFindOperation.query] for a type-safe projection of distinct values. + * + * @author Mark Paluch + * @since 2.3 + */ +inline fun ExecutableFindOperation.distinct(field : KProperty1): ExecutableFindOperation.TerminatingDistinct = + query(T::class.java).distinct(field.name) + /** * Extension for [ExecutableFindOperation.FindWithProjection.as] providing a [KClass] based variant. * @@ -78,3 +90,12 @@ fun ExecutableFindOperation.DistinctWithProjection.asType(resultType: */ inline fun ExecutableFindOperation.DistinctWithProjection.asType(): ExecutableFindOperation.TerminatingDistinct = `as`(T::class.java) + +/** + * Extension for [ExecutableFindOperation.FindDistinct.distinct] leveraging KProperty. + * + * @author Mark Paluch + * @since 2.3 + */ +fun ExecutableFindOperation.FindDistinct.distinct(key: KProperty<*>): ExecutableFindOperation.TerminatingDistinct = + distinct(asString(key)) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt index 1037c22c29..6772ab6237 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt @@ -20,7 +20,10 @@ import kotlinx.coroutines.reactive.asFlow import kotlinx.coroutines.reactive.awaitFirstOrNull import kotlinx.coroutines.reactive.awaitSingle import org.springframework.data.geo.GeoResult +import org.springframework.data.mongodb.core.query.asString import kotlin.reflect.KClass +import kotlin.reflect.KProperty +import kotlin.reflect.KProperty1 /** * Extension for [ReactiveFindOperation.query] providing a [KClass] based variant. @@ -41,6 +44,15 @@ fun ReactiveFindOperation.query(entityClass: KClass): ReactiveFindO inline fun ReactiveFindOperation.query(): ReactiveFindOperation.ReactiveFind = query(T::class.java) +/** + * Extension for [ReactiveFindOperation.query] for a type-safe projection of distinct values. + * + * @author Mark Paluch + * @since 2.3 + */ +inline fun ReactiveFindOperation.distinct(field : KProperty1): ReactiveFindOperation.TerminatingDistinct = + query(T::class.java).distinct(field.name) + /** * Extension for [ReactiveFindOperation.FindWithProjection.as] providing a [KClass] based variant. * @@ -79,6 +91,15 @@ fun ReactiveFindOperation.DistinctWithProjection.asType(resultType: KC inline fun ReactiveFindOperation.DistinctWithProjection.asType(): ReactiveFindOperation.TerminatingDistinct = `as`(T::class.java) +/** + * Extension for [ReactiveFindOperation.FindDistinct.distinct] leveraging KProperty. + * + * @author Mark Paluch + * @since 2.3 + */ +fun ReactiveFindOperation.FindDistinct.distinct(key: KProperty<*>): ReactiveFindOperation.TerminatingDistinct = + distinct(asString(key)) + /** * Non-nullable Coroutines variant of [ReactiveFindOperation.TerminatingFind.one]. * diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt index 624f110fb7..cbe6145511 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.core import example.first.First +import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.junit.Test @@ -32,6 +33,10 @@ class ExecutableFindOperationExtensionsTests { val distinctWithProjection = mockk(relaxed = true) + val findDistinct = mockk(relaxed = true) + + val executableFind = mockk>(relaxed = true) + @Test // DATAMONGO-1689 @Suppress("DEPRECATION") fun `ExecutableFindOperation#query(KClass) extension should call its Java counterpart`() { @@ -76,4 +81,25 @@ class ExecutableFindOperationExtensionsTests { distinctWithProjection.asType() verify { distinctWithProjection.`as`(User::class.java) } } + + @Test // DATAMONGO-2417 + fun `ExecutableFindOperation#distrinct() using KProperty1 should call its Java counterpart`() { + + every { operation.query(KotlinUser::class.java) } returns executableFind + + operation.distinct(KotlinUser::username) + verify { + operation.query(KotlinUser::class.java) + executableFind.distinct("username") + } + } + + @Test // DATAMONGO-2417 + fun `ExecutableFindOperation#FindDistinct#field() using KProperty should call its Java counterpart`() { + + findDistinct.distinct(KotlinUser::username) + verify { findDistinct.distinct("username") } + } + + data class KotlinUser(val username: String) } diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt index 117b95383f..b031b03f26 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt @@ -42,6 +42,10 @@ class ReactiveFindOperationExtensionsTests { val distinctWithProjection = mockk(relaxed = true) + val findDistinct = mockk(relaxed = true) + + val reactiveFind = mockk>(relaxed = true) + @Test // DATAMONGO-1719 @Suppress("DEPRECATION") fun `ReactiveFind#query(KClass) extension should call its Java counterpart`() { @@ -87,6 +91,25 @@ class ReactiveFindOperationExtensionsTests { verify { distinctWithProjection.`as`(User::class.java) } } + @Test // DATAMONGO-2417 + fun `ReactiveFind#distrinct() using KProperty1 should call its Java counterpart`() { + + every { operation.query(KotlinUser::class.java) } returns reactiveFind + + operation.distinct(KotlinUser::username) + verify { + operation.query(KotlinUser::class.java) + reactiveFind.distinct("username") + } + } + + @Test // DATAMONGO-2417 + fun `ReactiveFind#FindDistinct#field() using KProperty should call its Java counterpart`() { + + findDistinct.distinct(KotlinUser::username) + verify { findDistinct.distinct("username") } + } + @Test // DATAMONGO-2209 fun terminatingFindAwaitOneWithValue() { @@ -299,4 +322,6 @@ class ReactiveFindOperationExtensionsTests { spec.all() } } + + data class KotlinUser(val username: String) } From 632c499cf1a54a3c3e42b36d01e81a18bf3fde04 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 4 Feb 2020 08:41:00 +0100 Subject: [PATCH 0069/1381] DATAMONGO-2417 - Update Copyright headers of Kotlin extensions and test. Original Pull Request: #809 --- .../core/ExecutableAggregationOperationExtensions.kt | 2 +- .../data/mongodb/core/ExecutableFindOperationExtensions.kt | 6 +++--- .../mongodb/core/ExecutableInsertOperationExtensions.kt | 2 +- .../mongodb/core/ExecutableMapReduceOperationExtensions.kt | 2 +- .../mongodb/core/ExecutableRemoveOperationExtensions.kt | 2 +- .../mongodb/core/ExecutableUpdateOperationExtensions.kt | 2 +- .../data/mongodb/core/MongoOperationsExtensions.kt | 2 +- .../mongodb/core/ReactiveAggregationOperationExtensions.kt | 2 +- .../mongodb/core/ReactiveChangeStreamOperationExtensions.kt | 2 +- .../data/mongodb/core/ReactiveFindOperationExtensions.kt | 6 +++--- .../data/mongodb/core/ReactiveInsertOperationExtensions.kt | 2 +- .../mongodb/core/ReactiveMapReduceOperationExtensions.kt | 2 +- .../data/mongodb/core/ReactiveMongoOperationsExtensions.kt | 2 +- .../data/mongodb/core/ReactiveRemoveOperationExtensions.kt | 2 +- .../data/mongodb/core/ReactiveUpdateOperationExtensions.kt | 2 +- .../data/mongodb/core/query/CriteriaExtensions.kt | 2 +- .../data/mongodb/core/query/KPropertyPath.kt | 2 +- .../data/mongodb/core/query/TypedCriteriaExtensions.kt | 2 +- .../org/springframework/data/mongodb/core/Entities.kt | 2 +- .../core/ExecutableAggregationOperationExtensionsTests.kt | 2 +- .../mongodb/core/ExecutableFindOperationExtensionsTests.kt | 2 +- .../core/ExecutableInsertOperationExtensionsTests.kt | 2 +- .../core/ExecutableMapReduceOperationExtensionsTests.kt | 2 +- .../core/ExecutableRemoveOperationExtensionsTests.kt | 2 +- .../core/ExecutableUpdateOperationExtensionsTests.kt | 2 +- .../data/mongodb/core/MongoOperationsExtensionsTests.kt | 2 +- .../core/ReactiveAggregationOperationExtensionsTests.kt | 2 +- .../core/ReactiveChangeStreamOperationExtensionsTests.kt | 2 +- .../mongodb/core/ReactiveFindOperationExtensionsTests.kt | 2 +- .../mongodb/core/ReactiveInsertOperationExtensionsTests.kt | 2 +- .../core/ReactiveMapReduceOperationExtensionsTests.kt | 2 +- .../mongodb/core/ReactiveMongoOperationsExtensionsTests.kt | 2 +- .../mongodb/core/ReactiveRemoveOperationExtensionsTests.kt | 2 +- .../mongodb/core/ReactiveUpdateOperationExtensionsTests.kt | 2 +- .../data/mongodb/core/query/CriteriaExtensionsTests.kt | 2 +- .../data/mongodb/core/query/KPropertyPathTests.kt | 2 +- .../data/mongodb/core/query/TypedCriteriaExtensionsTests.kt | 2 +- 37 files changed, 41 insertions(+), 41 deletions(-) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt index 13195bc03a..2fd80c780d 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt index 15a5c18076..fdda7036eb 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. @@ -45,7 +45,7 @@ inline fun ExecutableFindOperation.query(): ExecutableFindOper * Extension for [ExecutableFindOperation.query] for a type-safe projection of distinct values. * * @author Mark Paluch - * @since 2.3 + * @since 3.0 */ inline fun ExecutableFindOperation.distinct(field : KProperty1): ExecutableFindOperation.TerminatingDistinct = query(T::class.java).distinct(field.name) @@ -95,7 +95,7 @@ inline fun ExecutableFindOperation.DistinctWithProjection.asTy * Extension for [ExecutableFindOperation.FindDistinct.distinct] leveraging KProperty. * * @author Mark Paluch - * @since 2.3 + * @since 3.0 */ fun ExecutableFindOperation.FindDistinct.distinct(key: KProperty<*>): ExecutableFindOperation.TerminatingDistinct = distinct(asString(key)) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt index 53e0195550..e4d9e661ea 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt index 6afff66125..62bf4bd21b 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt index 83b9f73dbf..306ccde4a7 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt index 58d23e0b4f..4b41d4fb46 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt index ae0982b823..0044210ea8 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt index 8d585ab74a..ac4eb370f9 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt index 264184e380..40bbc62b40 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt index 6772ab6237..7dd69438ba 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. @@ -48,7 +48,7 @@ inline fun ReactiveFindOperation.query(): ReactiveFindOperatio * Extension for [ReactiveFindOperation.query] for a type-safe projection of distinct values. * * @author Mark Paluch - * @since 2.3 + * @since 3.0 */ inline fun ReactiveFindOperation.distinct(field : KProperty1): ReactiveFindOperation.TerminatingDistinct = query(T::class.java).distinct(field.name) @@ -95,7 +95,7 @@ inline fun ReactiveFindOperation.DistinctWithProjection.asType * Extension for [ReactiveFindOperation.FindDistinct.distinct] leveraging KProperty. * * @author Mark Paluch - * @since 2.3 + * @since 3.0 */ fun ReactiveFindOperation.FindDistinct.distinct(key: KProperty<*>): ReactiveFindOperation.TerminatingDistinct = distinct(asString(key)) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt index 04425dc091..06a15e494f 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt index 772c643909..bb58c356b3 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt index 6ff2a95df2..714e22d5a7 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt index d855f6d94d..f0812542df 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt index 1bbba22e55..de1a94c50e 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt index e4be2a00b1..f7c52c8d4e 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt index ceeee61647..becfe9ca68 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt index c23d751ed3..92b784ea7b 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/Entities.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/Entities.kt index 40331c1328..bf58dc4d3a 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/Entities.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/Entities.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt index 841cb403fd..ba4786081c 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt index cbe6145511..27f4dcbaca 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt index 1a2d282b2f..f6065d425b 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensionsTests.kt index 242ae08807..27db1e580d 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt index 7d1abf20da..a17355b0a3 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensionsTests.kt index b76ce4b03f..3b7d972d3e 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt index ee70b344d3..90dd1472a1 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensionsTests.kt index 02390898d8..32a0f9c8ff 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensionsTests.kt index 1ce0337255..cbb2126682 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt index b031b03f26..ebef2d6edb 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensionsTests.kt index 0a2ab286e2..58e13a21ad 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensionsTests.kt index e17748ab4a..f724cacd53 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensionsTests.kt index 6b3d3e1b15..bf4b6a929d 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensionsTests.kt index 8192722351..2d95171298 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensionsTests.kt index 19f1a1b383..4593c1831d 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensionsTests.kt index ba6378f4c0..c56a42f22e 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt index 6df60cf9e7..03d68f7249 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt index 56386da25f..926ff1c096 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2020 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. From f6c62d6e2f58ab57add1330e413b8c372f3148fc Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 4 Feb 2020 09:30:14 +0100 Subject: [PATCH 0070/1381] DATAMONGO-2079 - MappingMongoConverter no longer implements ValueResolver. MappingMongoConverter no longer implements a package-private interface so that converter instances can be proxied. Original Pull Request: #832 --- .../mongodb/core/convert/MappingMongoConverter.java | 11 ++++++----- .../data/mongodb/core/convert/ValueResolver.java | 6 ++++-- 2 files changed, 10 insertions(+), 7 deletions(-) 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 5e87e77ec4..d40947f0e9 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 @@ -92,7 +92,7 @@ * @author Jordi Llach * @author Mark Paluch */ -public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver { +public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware { private static final String INCOMPATIBLE_TYPES = "Cannot convert %1$s of type %2$s into an instance of %3$s! Implement a custom Converter<%2$s, %3$s> and register it with the CustomConversions. Parent object was: %4$s"; private static final String INVALID_TYPE_TO_READ = "Expected to read Document %s into type %s but didn't find a PersistentEntity for the latter!"; @@ -132,7 +132,8 @@ public MappingMongoConverter(DbRefResolver dbRefResolver, this.idMapper = new QueryMapper(this); this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE); - this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, MappingMongoConverter.this); + this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, + MappingMongoConverter.this::getValueInternal); } /** @@ -432,7 +433,7 @@ private DbRefResolverCallback getDbRefResolverCallback(DocumentAccessor document SpELExpressionEvaluator evaluator) { return new DefaultDbRefResolverCallback(documentAccessor.getDocument(), currentPath, evaluator, - MappingMongoConverter.this); + MappingMongoConverter.this::getValueInternal); } private void readAssociation(Association association, PersistentPropertyAccessor accessor, @@ -1048,7 +1049,7 @@ protected DBRef createDBRef(Object target, MongoPersistentProperty property) { * (non-Javadoc) * @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.Document, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object) */ - @Override + @Nullable public Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, ObjectPath path) { return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop); @@ -1492,7 +1493,7 @@ public T getPropertyValue(MongoPersistentProperty property) { } DbRefResolverCallback callback = new DefaultDbRefResolverCallback(accessor.getDocument(), path, evaluator, - MappingMongoConverter.this); + MappingMongoConverter.this::getValueInternal); DBRef dbref = rawRefValue instanceof DBRef ? (DBRef) rawRefValue : null; return (T) dbRefResolver.resolveDbRef(property, dbref, callback, dbRefProxyHandler); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java index c449c715e1..f18593c3ba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java @@ -19,12 +19,14 @@ import org.bson.conversions.Bson; import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.lang.Nullable; /** * Internal API to trigger the resolution of properties. * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ interface ValueResolver { @@ -38,6 +40,6 @@ interface ValueResolver { * @param parent * @return */ - Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, - ObjectPath path); + @Nullable + Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, ObjectPath path); } From dd15bbc5c10cfa1c866314ff00efbad388361619 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 4 Feb 2020 09:34:27 +0100 Subject: [PATCH 0071/1381] DATAMONGO-2079 - Reduce visibility of MappingMongoConverter.getValueInternal. Do not expose a method that is used internally. Original Pull Request: #832 --- .../data/mongodb/core/convert/MappingMongoConverter.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 d40947f0e9..6dfb990bff 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 @@ -1045,12 +1045,8 @@ protected DBRef createDBRef(Object target, MongoPersistentProperty property) { throw new MappingException("No id property found on class " + entity.getType()); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.Document, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object) - */ @Nullable - public Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, + private Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, ObjectPath path) { return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop); } From 993018feb1fb8c865e5d3ea73a4e9a06b1588377 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 28 Jan 2020 15:58:33 +0100 Subject: [PATCH 0072/1381] DATAMONGO-2461 - Efficient resource usage and ci related improvments. - Give the server a little time to think on ci system. - Reuse and Close MongoClients in tests. - Use WriteConcern majority in setup. - Use longer transaction timeout on server - Use junit-pioneer to repeatable tests known to fail due to network errors. Original pull request: #831. --- Jenkinsfile | 20 +- spring-data-mongodb/pom.xml | 7 + .../core/MongoExceptionTranslator.java | 1 + .../ReactiveTransactionIntegrationTests.java | 54 +++--- ...iveMongoConfigurationIntegrationTests.java | 3 +- ...ctReactiveMongoConfigurationUnitTests.java | 3 +- ...uditingViaJavaConfigRepositoriesTests.java | 19 +- .../MongoDbFactoryParserIntegrationTests.java | 13 +- .../mongodb/config/ReactiveAuditingTests.java | 16 +- .../data/mongodb/core/ClientSessionTests.java | 44 ++--- .../core/DefaultScriptOperationsTests.java | 25 ++- .../ExecutableFindOperationSupportTests.java | 16 +- ...ExecutableRemoveOperationSupportTests.java | 16 +- ...ExecutableUpdateOperationSupportTests.java | 15 +- .../mongodb/core/JsonSchemaQueryTests.java | 39 ++-- .../core/MongoTemplateCollationTests.java | 22 +-- .../mongodb/core/MongoTemplateDbRefTests.java | 18 +- .../data/mongodb/core/MongoTemplateTests.java | 1 + .../core/MongoTemplateTransactionTests.java | 29 ++- .../core/MongoTemplateUpdateTests.java | 12 +- .../core/MongoTemplateValidationTests.java | 23 +-- .../data/mongodb/core/NoExplicitIdTests.java | 19 +- .../mongodb/core/QueryByExampleTests.java | 17 +- ...tiveChangeStreamOperationSupportTests.java | 34 ++-- .../core/ReactiveClientSessionTests.java | 25 ++- .../ReactiveFindOperationSupportTests.java | 21 ++- .../ReactiveMongoTemplateCollationTests.java | 23 +-- .../core/ReactiveMongoTemplateIndexTests.java | 36 ++-- ...ReactiveMongoTemplateTransactionTests.java | 24 +-- .../ReactiveMongoTemplateUpdateTests.java | 9 +- .../ReactiveRemoveOperationSupportTests.java | 21 ++- .../ReactiveUpdateOperationSupportTests.java | 21 ++- .../core/SessionBoundMongoTemplateTests.java | 30 ++- .../auditing/MongoTemplateAuditingTests.java | 15 +- .../ReactiveMongoTemplateAuditingTests.java | 19 +- .../convert/MappingMongoConverterTests.java | 14 +- .../data/mongodb/core/geo/GeoJsonTests.java | 18 +- .../core/index/IndexingIntegrationTests.java | 19 +- ...entEntityIndexCreatorIntegrationTests.java | 17 +- .../mongodb/core/index/TextIndexTests.java | 2 - .../mongodb/core/mapping/GeoIndexedTests.java | 10 +- .../event/ApplicationContextEventTests.java | 28 ++- .../core/messaging/ChangeStreamTests.java | 37 ++-- .../messaging/CursorReadingTaskUnitTests.java | 2 +- .../DefaultMessageListenerContainerTests.java | 13 +- .../core/messaging/TailableCursorTests.java | 28 +-- .../mongodb/core/query/CriteriaTests.java | 15 +- .../mongodb/core/query/TextQueryTests.java | 2 - .../core/schema/MongoJsonSchemaTests.java | 22 +-- .../schema/ReactiveMongoJsonSchemaTests.java | 23 +-- .../ComplexIdRepositoryIntegrationTests.java | 24 +-- .../PersonRepositoryTransactionalTests.java | 30 ++- .../ReactiveMongoRepositoryTests.java | 30 +-- .../data/mongodb/test/util/Client.java | 32 ++++ .../test/util/EnableIfMongoServerVersion.java | 2 + .../util/EnableIfReplicaSetAvailable.java | 2 + .../test/util/MongoClientExtension.java | 176 ++++++++++++++++++ .../mongodb/test/util/MongoTestUtils.java | 44 +++-- .../mongodb/test/util/MongoVersionRule.java | 2 +- .../data/mongodb/test/util/ReplSetClient.java | 32 ++++ .../src/test/resources/geospatial.xml | 3 +- .../src/test/resources/infrastructure.xml | 1 + .../src/test/resources/logback.xml | 1 + .../resources/reactive-infrastructure.xml | 1 + 64 files changed, 838 insertions(+), 502 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java diff --git a/Jenkinsfile b/Jenkinsfile index 5e8d695afe..d7b972c253 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -99,11 +99,11 @@ pipeline { steps { sh 'rm -rf ?' sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' sh 'sleep 10' sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' } } @@ -127,11 +127,11 @@ pipeline { steps { sh 'rm -rf ?' sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' sh 'sleep 10' sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' } } @@ -147,11 +147,11 @@ pipeline { steps { sh 'rm -rf ?' sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' sh 'sleep 10' sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' } } @@ -167,11 +167,11 @@ pipeline { steps { sh 'rm -rf ?' sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' sh 'sleep 10' sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Duser.name=jenkins -Dsort -U -B' } } @@ -187,11 +187,11 @@ pipeline { steps { sh 'rm -rf ?' sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' sh 'sleep 10' sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Dsort -U -B' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Duser.name=jenkins -Dsort -U -B' } } } diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 04cab785a3..76df2c09ee 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -250,6 +250,13 @@ test + + org.junit-pioneer + junit-pioneer + 0.5.3 + test + + javax.transaction jta diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index 20199306f2..e34950375a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -129,6 +129,7 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) { } else if (MongoDbErrorCodes.isTransactionFailureCode(code)) { return new MongoTransactionException(ex.getMessage(), ex); } + return new UncategorizedMongoDbException(ex.getMessage(), ex); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index de61724af0..b472e1c9a7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -18,6 +18,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -25,13 +26,12 @@ import java.time.Duration; import org.bson.types.ObjectId; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIfSystemProperty; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -40,11 +40,11 @@ import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.reactive.TransactionalOperator; import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -57,39 +57,43 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoServerCondition.class, MongoClientExtension.class }) +@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") +@EnableIfReplicaSetAvailable +@DisabledIfSystemProperty(named = "user.name", matches = "jenkins") public class ReactiveTransactionIntegrationTests { - public static @ClassRule RuleChain TEST_RULES = RuleChain.outerRule(MongoVersionRule.atLeast(Version.parse("4.0.0"))) - .around(ReplicaSet.required()); - private static final String DATABASE = "rxtx-test"; + + static @Client MongoClient mongoClient; + static GenericApplicationContext context; + PersonService personService; ReactiveMongoOperations operations; - static GenericApplicationContext context; - @BeforeClass + @BeforeAll public static void init() { context = new AnnotationConfigApplicationContext(TestMongoConfig.class, PersonService.class); } - @AfterClass + @AfterAll public static void after() { context.close(); } - @Before + @BeforeEach public void setUp() { personService = context.getBean(PersonService.class); operations = context.getBean(ReactiveMongoOperations.class); - MongoClient client = MongoTestUtils.reactiveClient(); + try (MongoClient client = MongoTestUtils.reactiveClient()) { - Flux.merge( // - MongoTestUtils.createOrReplaceCollection(DATABASE, operations.getCollectionName(Person.class), client), - MongoTestUtils.createOrReplaceCollection(DATABASE, operations.getCollectionName(EventLog.class), client) // - ).then().as(StepVerifier::create).verifyComplete(); + Flux.merge( // + MongoTestUtils.createOrReplaceCollection(DATABASE, operations.getCollectionName(Person.class), client), + MongoTestUtils.createOrReplaceCollection(DATABASE, operations.getCollectionName(EventLog.class), client) // + ).then().as(StepVerifier::create).verifyComplete(); + } } @Test // DATAMONGO-2265 @@ -222,7 +226,7 @@ static class TestMongoConfig extends AbstractReactiveMongoConfiguration { @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return mongoClient; } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java index 34414ae7c4..5bf0c189fe 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java @@ -19,6 +19,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; @@ -57,7 +58,7 @@ static class ReactiveConfiguration extends AbstractReactiveMongoConfiguration { @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return Mockito.mock(MongoClient.class); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java index 49c063ff8c..6cef594d69 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java @@ -26,6 +26,7 @@ import java.util.Set; import org.junit.Test; +import org.mockito.Mockito; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -182,7 +183,7 @@ protected String getDatabaseName() { @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return Mockito.mock(MongoClient.class); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java index 174006735a..53d42af97c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java @@ -22,10 +22,9 @@ import java.util.Optional; import java.util.function.Function; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -38,10 +37,12 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.stereotype.Repository; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; @@ -52,10 +53,12 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class AuditingViaJavaConfigRepositoriesTests { + static @Client MongoClient mongoClient; + @Autowired AuditablePersonRepository auditablePersonRepository; @Autowired AuditorAware auditorAware; @Autowired MongoMappingContext context; @@ -75,7 +78,7 @@ protected String getDatabaseName() { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Bean @@ -85,7 +88,7 @@ public AuditorAware auditorProvider() { } } - @Before + @BeforeEach public void setup() { auditablePersonRepository.deleteAll(); this.auditor = auditablePersonRepository.save(new AuditablePerson("auditor")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 309d85ebc8..1e03c7d280 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.*; +import com.mongodb.client.MongoClient; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; @@ -58,12 +59,14 @@ public void setUp() { @Test // DATAMONGO-2199 public void testWriteConcern() throws Exception { - SimpleMongoClientDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), - "database"); - dbFactory.setWriteConcern(WriteConcern.ACKNOWLEDGED); - dbFactory.getMongoDatabase(); + try(MongoClient client = MongoTestUtils.client()) { + SimpleMongoClientDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(client, + "database"); + dbFactory.setWriteConcern(WriteConcern.ACKNOWLEDGED); + dbFactory.getMongoDatabase(); - assertThat(ReflectionTestUtils.getField(dbFactory, "writeConcern")).isEqualTo(WriteConcern.ACKNOWLEDGED); + assertThat(ReflectionTestUtils.getField(dbFactory, "writeConcern")).isEqualTo(WriteConcern.ACKNOWLEDGED); + } } @Test // DATAMONGO-2199 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index 5c52460a11..3c1d29c536 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -25,8 +25,8 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -38,22 +38,24 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * Integration test for the auditing support via {@link org.springframework.data.mongodb.core.ReactiveMongoTemplate}. * * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class ReactiveAuditingTests { + static @Client MongoClient mongoClient; + @Autowired ReactiveAuditablePersonRepository auditablePersonRepository; @Autowired AuditorAware auditorAware; @Autowired MongoMappingContext context; @@ -71,7 +73,7 @@ protected String getDatabaseName() { @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return mongoClient; } @Bean diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index 3cc48a5c89..5c2ab969a4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -23,56 +23,50 @@ import lombok.Data; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.ReplSetClient; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.ClientSessionOptions; -import com.mongodb.client.MongoClient; import com.mongodb.client.ClientSession; +import com.mongodb.client.MongoClient; /** * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith({ MongoClientExtension.class }) +@EnableIfReplicaSetAvailable public class ClientSessionTests { - public static @ClassRule TestRule replSet = ReplicaSet.required(); - public @Rule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); - private static final String DB_NAME = "client-session-tests"; private static final String COLLECTION_NAME = "test"; + static @ReplSetClient MongoClient mongoClient; + MongoTemplate template; - MongoClient client; - @Before + @BeforeEach public void setUp() { - client = MongoTestUtils.replSetClient(); - - MongoTestUtils.createOrReplaceCollection(DB_NAME, COLLECTION_NAME, client); + MongoTestUtils.createOrReplaceCollection(DB_NAME, COLLECTION_NAME, mongoClient); - template = new MongoTemplate(client, DB_NAME); + template = new MongoTemplate(mongoClient, DB_NAME); template.getDb().getCollection(COLLECTION_NAME).insertOne(new Document("_id", "id-1").append("value", "spring")); } @Test // DATAMONGO-1880 public void shouldApplyClientSession() { - ClientSession session = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); assertThat(session.getOperationTime()).isNull(); @@ -89,7 +83,7 @@ public void shouldApplyClientSession() { @Test // DATAMONGO-2241 public void shouldReuseConfiguredInfrastructure() { - ClientSession session = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); MappingMongoConverter source = MappingMongoConverter.class.cast(template.getConverter()); MappingMongoConverter sessionTemplateConverter = MappingMongoConverter.class @@ -103,10 +97,9 @@ public void shouldReuseConfiguredInfrastructure() { } @Test // DATAMONGO-1920 - @MongoVersion(asOf = "3.7.3") public void withCommittedTransaction() { - ClientSession session = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); assertThat(session.getOperationTime()).isNull(); @@ -129,10 +122,9 @@ public void withCommittedTransaction() { } @Test // DATAMONGO-1920 - @MongoVersion(asOf = "3.7.3") public void withAbortedTransaction() { - ClientSession session = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); assertThat(session.getOperationTime()).isNull(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java index 6f6c8d9f1b..11af0f65a0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java @@ -20,11 +20,9 @@ import static org.springframework.data.mongodb.core.query.Query.*; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,13 +30,13 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.script.ExecutableMongoScript; import org.springframework.data.mongodb.core.script.NamedMongoScript; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.MongoClient; +import org.springframework.test.context.junit.jupiter.SpringExtension; /** * Integration tests for {@link DefaultScriptOperations}. @@ -47,11 +45,12 @@ * @author Oliver Gierke * @since 1.7 */ -@RunWith(SpringRunner.class) +@ExtendWith({MongoClientExtension.class, SpringExtension.class}) +@EnableIfMongoServerVersion(isLessThan = "4.1.0") @ContextConfiguration public class DefaultScriptOperationsTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_MOST_4_0 = MongoVersionRule.atMost(Version.parse("4.0.999")); + static @Client MongoClient mongoClient; @Configuration static class Config { @@ -60,7 +59,7 @@ static class Config { @Bean public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Bean @@ -78,7 +77,7 @@ public MongoTemplate template() throws Exception { @Autowired MongoTemplate template; DefaultScriptOperations scriptOps; - @Before + @BeforeEach public void setUp() { template.getCollection(JAVASCRIPT_COLLECTION_NAME).deleteMany(new Document()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java index 24d9862ee0..58c91e88d5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java @@ -29,8 +29,9 @@ import org.bson.BsonString; import org.bson.BsonValue; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -43,7 +44,10 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.NearQuery; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; + +import com.mongodb.client.MongoClient; /** * Integration tests for {@link ExecutableFindOperationSupport}. @@ -51,10 +55,12 @@ * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith(MongoClientExtension.class) public class ExecutableFindOperationSupportTests { private static final String STAR_WARS = "star-wars"; private static final String STAR_WARS_PLANETS = "star-wars-universe"; + static @Client MongoClient mongoClient; MongoTemplate template; Person han; @@ -63,11 +69,11 @@ public class ExecutableFindOperationSupportTests { Planet alderan; Planet dantooine; - @Before + @BeforeEach public void setUp() { template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableFindOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableFindOperationSupportTests")); template.dropCollection(STAR_WARS); template.dropCollection(STAR_WARS_PLANETS); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java index 7268bc4ba6..bbf9cabe01 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java @@ -23,12 +23,15 @@ import java.util.List; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import com.mongodb.client.MongoClient; import com.mongodb.client.result.DeleteResult; /** @@ -37,19 +40,22 @@ * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith(MongoClientExtension.class) public class ExecutableRemoveOperationSupportTests { private static final String STAR_WARS = "star-wars"; + static @Client MongoClient mongoClient; + MongoTemplate template; Person han; Person luke; - @Before + @BeforeEach public void setUp() { template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableRemoveOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableRemoveOperationSupportTests")); template.dropCollection(STAR_WARS); han = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java index ac897108a9..73a52737a6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java @@ -24,14 +24,17 @@ import java.util.Optional; import org.bson.BsonString; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import com.mongodb.client.MongoClient; import com.mongodb.client.result.UpdateResult; /** @@ -40,19 +43,21 @@ * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith(MongoClientExtension.class) public class ExecutableUpdateOperationSupportTests { private static final String STAR_WARS = "star-wars"; + static @Client MongoClient mongoClient; MongoTemplate template; Person han; Person luke; - @Before + @BeforeEach public void setUp() { template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); + new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableUpdateOperationSupportTests")); template.dropCollection(STAR_WARS); han = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java index 92f3b304ae..6ad794e763 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java @@ -24,43 +24,33 @@ import reactor.test.StepVerifier; import org.bson.Document; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; - /** * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith(MongoClientExtension.class) public class JsonSchemaQueryTests { public static final String DATABASE_NAME = "json-schema-query-tests"; - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); + static @Client MongoClient client; + static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient; - static MongoClient client = MongoTestUtils.client(); MongoTemplate template; Person jellyBelly, roseSpringHeart, kazmardBoombub; - @BeforeClass - public static void beforeClass() { - client = MongoTestUtils.client(); - } - - @Before + @BeforeEach public void setUp() { template = new MongoTemplate(client, DATABASE_NAME); @@ -108,10 +98,9 @@ public void findsDocumentsWithRequiredFieldsReactively() { MongoJsonSchema schema = MongoJsonSchema.builder().required("address").build(); - com.mongodb.reactivestreams.client.MongoClient mongoClient = MongoTestUtils.reactiveClient(); - - new ReactiveMongoTemplate(mongoClient, DATABASE_NAME).find(query(matchingDocumentStructure(schema)), Person.class) - .as(StepVerifier::create).expectNextCount(2).verifyComplete(); + new ReactiveMongoTemplate(reactiveClient, DATABASE_NAME) + .find(query(matchingDocumentStructure(schema)), Person.class).as(StepVerifier::create).expectNextCount(2) + .verifyComplete(); } @Test // DATAMONGO-1835 @@ -198,8 +187,8 @@ public void findsWithSchemaReturningRawDocument() { MongoJsonSchema schema = MongoJsonSchema.builder().required("address").build(); - assertThat(template.find(query(matchingDocumentStructure(schema)), Document.class, template.getCollectionName(Person.class))) - .hasSize(2); + assertThat(template.find(query(matchingDocumentStructure(schema)), Document.class, + template.getCollectionName(Person.class))).hasSize(2); } @Data diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java index f01fd6cde9..ed0607f4fb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java @@ -21,20 +21,18 @@ import java.util.Locale; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation.Alternate; import org.springframework.data.mongodb.core.query.Collation.ComparisonLevel; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; @@ -42,18 +40,18 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class MongoTemplateCollationTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_4_0 = MongoVersionRule.atLeast(Version.parse("3.4.0")); public static final String COLLECTION_NAME = "collation-1"; + static @Client MongoClient mongoClient; @Configuration static class Config extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Override @@ -69,7 +67,7 @@ protected boolean autoIndexCreation() { @Autowired MongoTemplate template; - @Before + @BeforeEach public void setUp() { template.dropCollection(COLLECTION_NAME); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java index 5f3cdf6d69..5f779f322c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java @@ -26,16 +26,19 @@ import java.util.List; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.convert.LazyLoadingProxy; import org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoId; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import com.mongodb.client.MongoClient; import com.mongodb.client.model.Filters; /** @@ -44,15 +47,18 @@ * * @author Christoph Strobl */ +@ExtendWith(MongoClientExtension.class) public class MongoTemplateDbRefTests { + static @Client MongoClient mongoClient; + MongoTemplate template; MongoTemplate otherDbTemplate; - @Before + @BeforeEach public void setUp() { - template = new MongoTemplate(MongoTestUtils.client(), "mongo-template-dbref-tests"); + template = new MongoTemplate(mongoClient, "mongo-template-dbref-tests"); template.dropCollection(RefCycleLoadingIntoDifferentTypeRoot.class); template.dropCollection(RefCycleLoadingIntoDifferentTypeIntermediate.class); @@ -64,7 +70,7 @@ public void setUp() { template.dropCollection(WithListRefToAnotherDb.class); template.dropCollection(WithLazyListRefToAnotherDb.class); - otherDbTemplate = new MongoTemplate(MongoTestUtils.client(), "mongo-template-dbref-tests-other-db"); + otherDbTemplate = new MongoTemplate(mongoClient, "mongo-template-dbref-tests-other-db"); otherDbTemplate.dropCollection(JustSomeType.class); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 217a86a42f..179363302d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -232,6 +232,7 @@ protected void cleanDb() { template.dropCollection(ImmutableAudited.class); template.dropCollection(RawStringId.class); template.dropCollection(Outer.class); + template.dropCollection(Message.class); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index b78a736b9a..ebc07dc146 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -27,11 +27,9 @@ import java.util.concurrent.CopyOnWriteArrayList; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -41,13 +39,12 @@ import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.test.util.AfterTransactionAssertion; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.ReplSetClient; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.transaction.AfterTransaction; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.transaction.annotation.Transactional; @@ -61,23 +58,23 @@ * @author Christoph Strobl * @currentRead Shadow's Edge - Brent Weeks */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) +@EnableIfReplicaSetAvailable @ContextConfiguration @Transactional(transactionManager = "txManager") public class MongoTemplateTransactionTests { - public static @ClassRule RuleChain TEST_RULES = RuleChain.outerRule(MongoVersionRule.atLeast(Version.parse("3.7.3"))) - .around(ReplicaSet.required()); - static final String DB_NAME = "template-tx-tests"; static final String COLLECTION_NAME = "assassins"; + static @ReplSetClient MongoClient mongoClient; + @Configuration static class Config extends AbstractMongoClientConfiguration { @Bean public MongoClient mongoClient() { - return MongoTestUtils.replSetClient(); + return mongoClient; } @Override @@ -101,7 +98,7 @@ MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { List>> assertionList; - @Before + @BeforeEach public void setUp() { template.setReadPreference(ReadPreference.primary()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index 1bbc4d464d..f0cb095bd2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -17,14 +17,14 @@ import static org.assertj.core.api.Assertions.*; +import lombok.EqualsAndHashCode; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; -import lombok.EqualsAndHashCode; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; @@ -38,7 +38,9 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -48,18 +50,18 @@ /** * @author Christoph Strobl */ -@ExtendWith(MongoServerCondition.class) +@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) class MongoTemplateUpdateTests { static final String DB_NAME = "update-test"; - MongoClient client; + static @Client MongoClient client; + MongoTemplate template; @BeforeEach void setUp() { - client = MongoTestUtils.client(); template = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, DB_NAME)); MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Score.class), client); 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 index 68dacbcc69..4550b7d465 100644 --- 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 @@ -25,10 +25,9 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataIntegrityViolationException; @@ -36,11 +35,10 @@ import org.springframework.data.mongodb.core.CollectionOptions.ValidationOptions; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.lang.Nullable; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; import com.mongodb.client.model.ValidationAction; @@ -54,19 +52,18 @@ * @author Andreas Zink * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class MongoTemplateValidationTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_2_0 = MongoVersionRule.atLeast(Version.parse("3.2.0")); - static final String COLLECTION_NAME = "validation-1"; + static @Client MongoClient mongoClient; @Configuration static class Config extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Override @@ -82,7 +79,7 @@ protected boolean autoIndexCreation() { @Autowired MongoTemplate template; - @Before + @BeforeEach public void setUp() { template.dropCollection(COLLECTION_NAME); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java index a4398ce899..d228f742d4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java @@ -22,17 +22,18 @@ import java.util.Map; import java.util.Optional; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; @@ -42,10 +43,12 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class NoExplicitIdTests { + static @Client MongoClient mongoClient; + @Configuration @EnableMongoRepositories(considerNestedRepositories = true) static class Config extends AbstractMongoClientConfiguration { @@ -57,7 +60,7 @@ protected String getDatabaseName() { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Override @@ -69,7 +72,7 @@ protected boolean autoIndexCreation() { @Autowired MongoOperations mongoOps; @Autowired TypeWithoutExplicitIdPropertyRepository repo; - @Before + @BeforeEach public void setUp() { mongoOps.dropCollection(TypeWithoutIdProperty.class); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java index c1a5503156..34e719dd1d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java @@ -22,8 +22,9 @@ import java.util.List; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; @@ -32,7 +33,10 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UntypedExampleMatcher; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; + +import com.mongodb.client.MongoClient; /** * Integration tests for Query-by-example. @@ -41,15 +45,18 @@ * @author Mark Paluch * @author Oliver Gierke */ +@ExtendWith(MongoClientExtension.class) public class QueryByExampleTests { + static @Client MongoClient mongoClient; + MongoOperations operations; Person p1, p2, p3; - @Before + @BeforeEach public void setUp() { - operations = new MongoTemplate(MongoTestUtils.client(), "query-by-example"); + operations = new MongoTemplate(mongoClient, "query-by-example"); operations.remove(new Query(), Person.class); p1 = new Person(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java index 5134f20d13..4869983fa1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java @@ -19,6 +19,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import lombok.SneakyThrows; +import org.springframework.data.mongodb.test.util.ReplSetClient; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; @@ -29,13 +30,14 @@ import java.util.stream.Collectors; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.ReplicaSet; import com.mongodb.reactivestreams.client.MongoClient; @@ -45,26 +47,26 @@ * @author Christoph Strobl * @currentRead Dawn Cook - The Decoy Princess */ +@ExtendWith(MongoClientExtension.class) +@EnableIfReplicaSetAvailable public class ReactiveChangeStreamOperationSupportTests { - public static @ClassRule ReplicaSet REPL_SET_REQUIRED = ReplicaSet.required(); static final String DATABASE_NAME = "rx-change-stream"; + static @ReplSetClient MongoClient mongoClient; - MongoClient client; ReactiveMongoTemplate template; - @Before + @BeforeEach public void setUp() { - client = MongoTestUtils.reactiveReplSetClient(); - template = new ReactiveMongoTemplate(client, DATABASE_NAME); + template = new ReactiveMongoTemplate(mongoClient, DATABASE_NAME); - MongoTestUtils.createOrReplaceCollectionNow(DATABASE_NAME, "person", client); + MongoTestUtils.createOrReplaceCollectionNow(DATABASE_NAME, "person", mongoClient); } - @After + @AfterEach public void tearDown() { - MongoTestUtils.dropCollectionNow(DATABASE_NAME, "person", client); + MongoTestUtils.dropCollectionNow(DATABASE_NAME, "person", mongoClient); } @SneakyThrows @@ -125,8 +127,8 @@ public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedExc Thread.sleep(500); // just give it some time to link receive all events try { - assertThat(documents.stream().map(ChangeStreamEvent::getBody).collect(Collectors.toList())) - .containsOnly(person1, person2, person3); + assertThat(documents.stream().map(ChangeStreamEvent::getBody).collect(Collectors.toList())).containsOnly(person1, + person2, person3); } finally { disposable.dispose(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java index 012edc39ca..3ee00c6931 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java @@ -26,15 +26,14 @@ import java.util.function.Supplier; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.TestRule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; import com.mongodb.ClientSessionOptions; import com.mongodb.reactivestreams.client.ClientSession; @@ -45,22 +44,20 @@ * @author Mark Paluch * @currentRead Beyond the Shadows - Brent Weeks */ +@ExtendWith(MongoClientExtension.class) +@EnableIfReplicaSetAvailable public class ReactiveClientSessionTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); - public static @ClassRule TestRule replSet = ReplicaSet.required(); - static final String DATABASE_NAME = "reflective-client-session-tests"; static final String COLLECTION_NAME = "test"; - MongoClient client; + static @Client MongoClient client; + ReactiveMongoTemplate template; - @Before + @BeforeEach public void setUp() { - client = MongoTestUtils.reactiveReplSetClient(); - template = new ReactiveMongoTemplate(client, DATABASE_NAME); MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, COLLECTION_NAME, client) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java index af98e55d75..1b5d2127e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java @@ -35,8 +35,9 @@ import org.bson.BsonString; import org.bson.BsonValue; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -48,7 +49,10 @@ import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; + +import com.mongodb.client.MongoClient; /** * Integration tests for {@link ReactiveFindOperationSupport}. @@ -56,25 +60,28 @@ * @author Mark Paluch * @author Christoph Strobl */ +@ExtendWith(MongoClientExtension.class) public class ReactiveFindOperationSupportTests { private static final String STAR_WARS = "star-wars"; MongoTemplate blocking; ReactiveMongoTemplate template; + static @Client MongoClient client; + static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient; + Person han; Person luke; - @Before + @BeforeEach public void setUp() { - blocking = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableFindOperationSupportTests")); + blocking = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, "ExecutableFindOperationSupportTests")); recreateCollection(STAR_WARS, false); insertObjects(); - template = new ReactiveMongoTemplate(MongoTestUtils.reactiveClient(), "ExecutableFindOperationSupportTests"); + template = new ReactiveMongoTemplate(reactiveClient, "ExecutableFindOperationSupportTests"); } void insertObjects() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java index d94b0e1836..53f95e070b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java @@ -24,20 +24,17 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; import org.springframework.data.mongodb.core.query.Collation; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.reactivestreams.client.MongoClient; @@ -45,19 +42,19 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class ReactiveMongoTemplateCollationTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_4_0 = MongoVersionRule.atLeast(Version.parse("3.4.0")); public static final String COLLECTION_NAME = "collation-1"; + static @Client MongoClient mongoClient; @Configuration static class Config extends AbstractReactiveMongoConfiguration { @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return mongoClient; } @Override @@ -68,7 +65,7 @@ protected String getDatabaseName() { @Autowired ReactiveMongoTemplate template; - @Before + @BeforeEach public void setUp() { template.dropCollection(COLLECTION_NAME).as(StepVerifier::create).verifyComplete(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index 4be37b3f0a..a956372c4b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -28,11 +28,11 @@ import java.util.concurrent.TimeUnit; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junitpioneer.jupiter.RepeatFailedTest; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort.Direction; @@ -40,9 +40,9 @@ import org.springframework.data.mongodb.core.index.IndexField; import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.client.model.IndexOptions; import com.mongodb.reactivestreams.client.ListIndexesPublisher; @@ -54,26 +54,30 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:reactive-infrastructure.xml") +@ExtendWith(MongoClientExtension.class) public class ReactiveMongoTemplateIndexTests { - @Autowired SimpleReactiveMongoDatabaseFactory factory; - @Autowired ReactiveMongoTemplate template; - @Autowired MongoClient client; + static @Client MongoClient client; - @Before + SimpleReactiveMongoDatabaseFactory factory; + ReactiveMongoTemplate template; + + @BeforeEach public void setUp() { + factory = new SimpleReactiveMongoDatabaseFactory(client, "reactive-template-index-tests"); + template = new ReactiveMongoTemplate(factory); + MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "person", client); MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "indexfail", client); MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "indexedSample", client); } - @After + @AfterEach public void cleanUp() {} @Test // DATAMONGO-1444 + @RepeatFailedTest(3) public void testEnsureIndexShouldCreateIndex() { Person p1 = new Person("Oliver"); @@ -109,6 +113,7 @@ public void testEnsureIndexShouldCreateIndex() { } @Test // DATAMONGO-1444 + @RepeatFailedTest(3) public void getIndexInfoShouldReturnCorrectIndex() { Person p1 = new Person("Oliver"); @@ -139,6 +144,7 @@ public void getIndexInfoShouldReturnCorrectIndex() { } @Test // DATAMONGO-1444, DATAMONGO-2264 + @RepeatFailedTest(3) public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { template.indexOps(Person.class).dropAllIndexes() // @@ -190,6 +196,7 @@ public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { } @Test // DATAMONGO-1928 + @RepeatFailedTest(3) public void shouldCreateIndexOnAccess() { StepVerifier.create(template.getCollection("indexedSample").listIndexes(Document.class)).expectNextCount(0) @@ -205,6 +212,7 @@ public void shouldCreateIndexOnAccess() { } @Test // DATAMONGO-1928, DATAMONGO-2264 + @RepeatFailedTest(3) public void indexCreationShouldFail() throws InterruptedException { Flux.from(factory.getMongoDatabase().getCollection("indexfail") // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java index 6fdf4d8701..ce81645e8b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java @@ -26,17 +26,16 @@ import java.util.stream.Collectors; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.TestRule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.reactivestreams.Publisher; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; import com.mongodb.ClientSessionOptions; import com.mongodb.reactivestreams.client.ClientSession; @@ -49,11 +48,10 @@ * @author Mark Paluch * @currentRead The Core - Peter V. Brett */ +@ExtendWith(MongoClientExtension.class) +@EnableIfReplicaSetAvailable public class ReactiveMongoTemplateTransactionTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_7_5 = MongoVersionRule.atLeast(Version.parse("3.7.5")); - public static @ClassRule TestRule replSet = ReplicaSet.required(); - static final String DATABASE_NAME = "reactive-template-tx-tests"; static final String COLLECTION_NAME = "test"; static final Document DOCUMENT = new Document("_id", "id-1").append("value", "spring"); @@ -64,14 +62,12 @@ public class ReactiveMongoTemplateTransactionTests { static final Person LEESHA = new Person("leesha", 22); static final Person RENNA = new Person("renna", 22); - MongoClient client; + static @Client MongoClient client; ReactiveMongoTemplate template; - @Before + @BeforeEach public void setUp() { - client = MongoTestUtils.reactiveReplSetClient(); - template = new ReactiveMongoTemplate(client, DATABASE_NAME); MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, COLLECTION_NAME, client).as(StepVerifier::create) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java index d3fbc3b7a6..c75e737437 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java @@ -27,7 +27,6 @@ import java.util.List; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; @@ -40,8 +39,9 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; -import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; import com.mongodb.reactivestreams.client.MongoClient; @@ -50,19 +50,18 @@ /** * @author Christoph Strobl */ -@ExtendWith(MongoServerCondition.class) +@ExtendWith(MongoClientExtension.class) @EnableIfMongoServerVersion(isGreaterThanEqual = "4.2") public class ReactiveMongoTemplateUpdateTests { static final String DB_NAME = "reactive-update-test"; - MongoClient client; + static @Client MongoClient client; ReactiveMongoTemplate template; @BeforeEach void beforeEach() { - client = MongoTestUtils.reactiveClient(); template = new ReactiveMongoTemplate(new SimpleReactiveMongoDatabaseFactory(client, DB_NAME)); MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Score.class), client).then() diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java index 0be743d9d2..7b0d30c193 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java @@ -22,31 +22,38 @@ import lombok.Data; import reactor.test.StepVerifier; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; + +import com.mongodb.client.MongoClient; /** * Integration tests for {@link ReactiveRemoveOperationSupport}. * * @author Mark Paluch */ +@ExtendWith(MongoClientExtension.class) public class ReactiveRemoveOperationSupportTests { private static final String STAR_WARS = "star-wars"; + static @Client MongoClient client; + static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient; + MongoTemplate blocking; ReactiveMongoTemplate template; Person han; Person luke; - @Before + @BeforeEach public void setUp() { - blocking = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableRemoveOperationSupportTests")); + blocking = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, "ExecutableRemoveOperationSupportTests")); blocking.dropCollection(STAR_WARS); han = new Person(); @@ -60,7 +67,7 @@ public void setUp() { blocking.save(han); blocking.save(luke); - template = new ReactiveMongoTemplate(MongoTestUtils.reactiveClient(), "ExecutableRemoveOperationSupportTests"); + template = new ReactiveMongoTemplate(reactiveClient, "ExecutableRemoveOperationSupportTests"); } @Test // DATAMONGO-1719 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java index 756d1c288c..c16d04d6d8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java @@ -23,33 +23,40 @@ import reactor.test.StepVerifier; import org.bson.BsonString; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; + +import com.mongodb.client.MongoClient; /** * Integration tests for {@link ReactiveUpdateOperationSupport}. * * @author Mark Paluch */ +@ExtendWith(MongoClientExtension.class) public class ReactiveUpdateOperationSupportTests { private static final String STAR_WARS = "star-wars"; + static @Client MongoClient client; + static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient; + MongoTemplate blocking; ReactiveMongoTemplate template; Person han; Person luke; - @Before + @BeforeEach public void setUp() { - blocking = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); + blocking = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, "ExecutableUpdateOperationSupportTests")); blocking.dropCollection(STAR_WARS); han = new Person(); @@ -63,7 +70,7 @@ public void setUp() { blocking.save(han); blocking.save(luke); - template = new ReactiveMongoTemplate(MongoTestUtils.reactiveClient(), "ExecutableUpdateOperationSupportTests"); + template = new ReactiveMongoTemplate(reactiveClient, "ExecutableUpdateOperationSupportTests"); } @Test // DATAMONGO-1719 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java index fcce51f500..2e64c0d978 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java @@ -36,12 +36,10 @@ import org.aopalliance.aop.Advice; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.springframework.aop.Advisor; import org.springframework.aop.framework.Advised; @@ -63,11 +61,10 @@ import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.ReplSetClient; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.ClientSessionOptions; @@ -81,24 +78,21 @@ * * @author Christoph Strobl */ +@ExtendWith(MongoClientExtension.class) +@EnableIfReplicaSetAvailable public class SessionBoundMongoTemplateTests { - public static @ClassRule TestRule replSet = ReplicaSet.required(); + static @ReplSetClient MongoClient client; - public @Rule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); - - MongoClient client; MongoTemplate template; SessionBoundMongoTemplate sessionBoundTemplate; ClientSession session; volatile List> spiedCollections = new ArrayList<>(); volatile List spiedDatabases = new ArrayList<>(); - @Before + @BeforeEach public void setUp() { - client = MongoTestUtils.replSetClient(); - MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, "session-bound-mongo-template-tests") { @Override @@ -147,7 +141,7 @@ private void injectCollectionSpy(MongoCollection collection) { }; } - @After + @AfterEach public void tearDown() { session.close(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index a4a321ea4a..b8d0ed1506 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -21,8 +21,8 @@ import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.annotation.Id; @@ -34,24 +34,27 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; /** * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class MongoTemplateAuditingTests { + static @Client MongoClient mongoClient; + @Configuration @EnableMongoAuditing static class Conf extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 3095799f73..752c99cbfc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -24,9 +24,9 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -40,20 +40,23 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class ReactiveMongoTemplateAuditingTests { static final String DB_NAME = "mongo-template-audit-tests"; + static @Client MongoClient mongoClient; + @Configuration @EnableMongoAuditing static class Conf extends AbstractReactiveMongoConfiguration { @@ -61,7 +64,7 @@ static class Conf extends AbstractReactiveMongoConfiguration { @Bean @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return mongoClient; } @Override @@ -73,7 +76,7 @@ protected String getDatabaseName() { @Autowired ReactiveMongoTemplate template; @Autowired MongoClient client; - @Before + @BeforeEach public void setUp() { MongoTestUtils.flushCollection(DB_NAME, template.getCollectionName(ImmutableAuditableEntityWithVersion.class), diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index 31dd079cc9..f44a367f39 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -28,14 +28,16 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.client.MongoClient; @@ -44,18 +46,18 @@ * * @author Christoph Strobl */ +@ExtendWith(MongoClientExtension.class) public class MappingMongoConverterTests { - MongoClient client; + static @Client MongoClient client; MappingMongoConverter converter; MongoMappingContext mappingContext; DbRefResolver dbRefResolver; - @Before + @BeforeEach public void setUp() { - client = MongoTestUtils.client(); client.getDatabase("mapping-converter-tests").drop(); MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, "mapping-converter-tests"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index 844e9c16bc..3adc352e7a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -27,7 +27,10 @@ import org.assertj.core.data.Percentage; import org.junit.After; import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -47,8 +50,11 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.BasicDbListBuilder; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; @@ -60,10 +66,12 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({MongoClientExtension.class, SpringExtension.class}) @ContextConfiguration public class GeoJsonTests { + static @Client MongoClient mongoClient; + @Configuration static class TestConfig extends AbstractMongoClientConfiguration { @@ -74,13 +82,13 @@ protected String getDatabaseName() { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } } @Autowired MongoTemplate template; - @Before + @BeforeEach public void setUp() { template.setWriteConcern(WriteConcern.JOURNALED); @@ -89,7 +97,7 @@ public void setUp() { addVenues(); } - @After + @AfterEach public void tearDown() { dropIndex(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 3688aef58d..31dfbc0f0b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -28,9 +28,9 @@ import java.util.List; import java.util.Optional; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -45,10 +45,11 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; @@ -60,10 +61,12 @@ * @author Jordi Llach * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class IndexingIntegrationTests { + static @Client MongoClient mongoClient; + @Autowired MongoOperations operations; @Autowired MongoDatabaseFactory mongoDbFactory; @Autowired ConfigurableApplicationContext context; @@ -73,7 +76,7 @@ static class Config extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Override @@ -87,7 +90,7 @@ TimeoutResolver myTimeoutResolver() { } } - @After + @AfterEach public void tearDown() { operations.dropCollection(IndexedPerson.class); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java index 371bfa800e..41a11f1728 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; +import com.mongodb.client.MongoClient; import org.hamcrest.core.IsInstanceOf; import org.junit.ClassRule; import org.junit.Rule; @@ -98,16 +99,18 @@ public void createIndexShouldThrowMeaningfulExceptionWhenIndexCreationFails() { expectedException.expectMessage("lastname"); expectedException.expectCause(IsInstanceOf. instanceOf(MongoCommandException.class)); - MongoTemplate mongoTemplate = new MongoTemplate(MongoTestUtils.client(), "issue"); + try(MongoClient client = MongoTestUtils.client()) { + MongoTemplate mongoTemplate = new MongoTemplate(client, "issue"); - MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(new MongoMappingContext(), - mongoTemplate); + MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(new MongoMappingContext(), + mongoTemplate); - indexCreator.createIndex(new IndexDefinitionHolder("dalinar.kohlin", - new Index().named("stormlight").on("lastname", Direction.ASC).unique(), "datamongo-1125")); + indexCreator.createIndex(new IndexDefinitionHolder("dalinar.kohlin", + new Index().named("stormlight").on("lastname", Direction.ASC).unique(), "datamongo-1125")); - indexCreator.createIndex(new IndexDefinitionHolder("dalinar.kohlin", - new Index().named("stormlight").on("lastname", Direction.ASC).sparse(), "datamongo-1125")); + indexCreator.createIndex(new IndexDefinitionHolder("dalinar.kohlin", + new Index().named("stormlight").on("lastname", Direction.ASC).sparse(), "datamongo-1125")); + } } @Document(RECURSIVE_TYPE_COLLECTION_NAME) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java index fbd50f5895..ea592097a9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java @@ -42,8 +42,6 @@ */ public class TextIndexTests extends AbstractIntegrationTests { - public static @ClassRule MongoVersionRule version = MongoVersionRule.atLeast(new Version(2, 6)); - private @Autowired MongoTemplate template; private IndexOperations indexOps; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java index 4e9e5280c7..b5fde7dd64 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java @@ -66,11 +66,13 @@ public void cleanUp() { private void cleanDb() { - MongoClient mongo = MongoTestUtils.client(); - MongoDatabase db = mongo.getDatabase(GeoIndexedAppConfig.GEO_DB); + try(MongoClient mongo = MongoTestUtils.client()) { - for (String coll : collectionsToDrop) { - db.getCollection(coll).drop(); + MongoDatabase db = mongo.getDatabase(GeoIndexedAppConfig.GEO_DB); + + for (String coll : collectionsToDrop) { + db.getCollection(coll).drop(); + } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java index 31380caec7..125ddf536c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java @@ -20,7 +20,6 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; -import com.mongodb.client.MongoClients; import lombok.AllArgsConstructor; import lombok.Data; @@ -29,11 +28,10 @@ import java.util.List; import java.util.Map; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.data.annotation.Id; @@ -46,7 +44,8 @@ import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory; import org.springframework.data.mongodb.repository.support.QuerydslMongoPredicateExecutor; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; @@ -60,6 +59,7 @@ * @author Jordi Llach * @author Mark Paluch */ +@ExtendWith({ MongoClientExtension.class }) public class ApplicationContextEventTests { private static final String COLLECTION_NAME = "personPojoStringId"; @@ -69,17 +69,13 @@ public class ApplicationContextEventTests { private final String[] collectionsToDrop = new String[] { COLLECTION_NAME, ROOT_COLLECTION_NAME, RELATED_COLLECTION_NAME }; - private static MongoClient mongo; + static @Client MongoClient mongoClient; + private ApplicationContext applicationContext; private MongoTemplate template; private SimpleMappingEventListener listener; - @BeforeClass - public static void beforeClass() { - mongo = MongoTestUtils.client(); - } - - @Before + @BeforeEach public void setUp() { cleanDb(); @@ -90,14 +86,14 @@ public void setUp() { listener = applicationContext.getBean(SimpleMappingEventListener.class); } - @After + @AfterEach public void cleanUp() { cleanDb(); } private void cleanDb() { - MongoDatabase db = mongo.getDatabase("database"); + MongoDatabase db = mongoClient.getDatabase("database"); for (String coll : collectionsToDrop) { db.getCollection(coll).drop(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index 7c2e9cc8b8..80eaac7ed7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -34,14 +34,12 @@ import org.bson.BsonDocument; import org.bson.Document; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.Field; @@ -50,12 +48,12 @@ import org.springframework.data.mongodb.core.messaging.SubscriptionUtils.*; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.ReplSetClient; +import com.mongodb.client.MongoClient; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; @@ -66,10 +64,11 @@ * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith({ MongoClientExtension.class }) +@EnableIfReplicaSetAvailable public class ChangeStreamTests { - public static @ClassRule TestRule replSet = ReplicaSet.required(); - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.atLeast(Version.parse("3.6")); + static @ReplSetClient MongoClient mongoClient; static ThreadPoolExecutor executor; MongoTemplate template; @@ -79,15 +78,15 @@ public class ChangeStreamTests { User huffyFluffy; User sugarSplashy; - @BeforeClass + @BeforeAll public static void beforeClass() { executor = new ThreadPoolExecutor(2, 2, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); } - @Before + @BeforeEach public void setUp() { - template = new MongoTemplate(MongoTestUtils.replSetClient(), "change-stream-tests"); + template = new MongoTemplate(mongoClient, "change-stream-tests"); template.dropCollection(User.class); container = new DefaultMessageListenerContainer(template, executor); @@ -109,12 +108,12 @@ public void setUp() { sugarSplashy.age = 5; } - @After + @AfterEach public void tearDown() { container.stop(); } - @AfterClass + @AfterAll public static void afterClass() { executor.shutdown(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java index 146460ea11..10527e30cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java @@ -46,7 +46,7 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@RunWith(MockitoJUnitRunner.Silent.class) public class CursorReadingTaskUnitTests { @Mock MongoDatabase db; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index 66323d31c9..f0fdbfa246 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -27,6 +27,10 @@ import java.util.stream.Collectors; import org.bson.Document; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -37,11 +41,14 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; +import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.util.ErrorHandler; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.changestream.ChangeStreamDocument; @@ -51,7 +58,7 @@ * * @author Christoph Strobl */ -@ExtendWith(MongoServerCondition.class) +@ExtendWith({MongoClientExtension.class, MongoServerCondition.class}) public class DefaultMessageListenerContainerTests { public static final String DATABASE_NAME = "change-stream-events"; @@ -60,6 +67,8 @@ public class DefaultMessageListenerContainerTests { public static final Duration TIMEOUT = Duration.ofSeconds(2); + static @Client MongoClient client; + MongoDatabaseFactory dbFactory; MongoCollection collection; MongoCollection collection2; @@ -70,7 +79,7 @@ public class DefaultMessageListenerContainerTests { @BeforeEach void beforeEach() { - dbFactory = new SimpleMongoClientDatabaseFactory(MongoTestUtils.client(), DATABASE_NAME); + dbFactory = new SimpleMongoClientDatabaseFactory(client, DATABASE_NAME); template = new MongoTemplate(dbFactory); template.dropCollection(COLLECTION_NAME); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java index a62ad17522..2e723df5b1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java @@ -27,18 +27,22 @@ import java.util.concurrent.TimeUnit; import org.bson.Document; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.CollectionOptions; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.messaging.Message.MessageProperties; import org.springframework.data.mongodb.core.messaging.TailableCursorRequest.TailableCursorRequestOptions; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; + +import com.mongodb.client.MongoClient; /** * Integration test for subscribing to a capped {@link com.mongodb.client.MongoCollection} inside the @@ -47,10 +51,12 @@ * @author Christoph Strobl * @author Mark Paluch */ +@ExtendWith({ MongoClientExtension.class }) public class TailableCursorTests { static final String COLLECTION_NAME = "user"; + static @Client MongoClient mongoClient; static ThreadPoolExecutor executor; MongoTemplate template; MessageListenerContainer container; @@ -59,15 +65,15 @@ public class TailableCursorTests { User huffyFluffy; User sugarSplashy; - @BeforeClass + @BeforeAll public static void beforeClass() { executor = new ThreadPoolExecutor(2, 2, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); } - @Before + @BeforeEach public void setUp() { - template = new MongoTemplate(MongoTestUtils.client(), "tailable-cursor-tests"); + template = new MongoTemplate(mongoClient, "tailable-cursor-tests"); template.dropCollection(User.class); template.createCollection(User.class, CollectionOptions.empty().capped().maxDocuments(10000).size(10000)); @@ -91,12 +97,12 @@ public void setUp() { sugarSplashy.age = 5; } - @After + @AfterEach public void tearDown() { container.stop(); } - @AfterClass + @AfterAll public static void afterClass() { executor.shutdown(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java index bd7d0a352d..ee1bf6dc8d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java @@ -27,7 +27,9 @@ import java.util.Arrays; import org.bson.types.Binary; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.MongoOperations; @@ -45,8 +47,8 @@ */ public class CriteriaTests { + static MongoClient client; MongoOperations ops; - MongoClient client; static final DocumentWithBitmask FIFTY_FOUR/*00110110*/ = new DocumentWithBitmask("1", Integer.valueOf(54), Integer.toBinaryString(54)); @@ -57,10 +59,19 @@ public class CriteriaTests { static final DocumentWithBitmask ONE_HUNDRED_TWO/*01100110*/ = new DocumentWithBitmask("4", new Binary(Base64Utils.decodeFromString("Zg==")), "01100110"); + @BeforeClass + public static void beforeClass() { + client = MongoTestUtils.client(); + } + + @AfterClass + public static void afterClass() { + client.close(); + } + @Before public void setUp() { - client = MongoTestUtils.client(); ops = new MongoTemplate(client, "criteria-tests"); ops.dropCollection(DocumentWithBitmask.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java index 44baf0092f..56860f6aad 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java @@ -47,8 +47,6 @@ */ public class TextQueryTests extends AbstractIntegrationTests { - public static @ClassRule MongoVersionRule version = MongoVersionRule.atLeast(new Version(2, 6)); - private static final FullTextDoc BAKE = new FullTextDocBuilder().headline("bake").build(); private static final FullTextDoc COFFEE = new FullTextDocBuilder().subHeadline("coffee").build(); private static final FullTextDoc CAKE = new FullTextDocBuilder().body("cake").build(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java index 90bec67bf2..37d028c80a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java @@ -23,10 +23,9 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; @@ -35,11 +34,10 @@ import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.validation.Validator; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; @@ -53,18 +51,18 @@ * * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class MongoJsonSchemaTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); + static @Client MongoClient mongoClient; @Configuration static class Config extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } @Override @@ -75,7 +73,7 @@ protected String getDatabaseName() { @Autowired MongoTemplate template; - @Before + @BeforeEach public void setUp() { template.dropCollection(Person.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java index a0310ae8f6..43af21cd94 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java @@ -24,10 +24,9 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataRetrievalFailureException; @@ -36,32 +35,30 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper; import org.springframework.data.mongodb.core.mapping.Field; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * Integration tests for {@link MongoJsonSchema} using reactive infrastructure. * * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class ReactiveMongoJsonSchemaTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); + static @Client MongoClient mongoClient; @Configuration static class Config extends AbstractReactiveMongoConfiguration { @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return mongoClient; } @Override @@ -72,7 +69,7 @@ protected String getDatabaseName() { @Autowired ReactiveMongoTemplate template; - @Before + @BeforeEach public void setUp() { template.dropCollection(Person.class).as(StepVerifier::create).verifyComplete(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java index 247f958c89..a9488c1cf7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java @@ -22,20 +22,17 @@ import java.util.List; import java.util.Optional; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; @@ -44,11 +41,10 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class ComplexIdRepositoryIntegrationTests { - public @Rule MongoVersionRule mongoVersionRule = MongoVersionRule.any(); + static @Client MongoClient mongoClient; @Configuration @EnableMongoRepositories @@ -61,7 +57,7 @@ protected String getDatabaseName() { @Override public MongoClient mongoClient() { - return MongoTestUtils.client(); + return mongoClient; } } @@ -72,7 +68,7 @@ public MongoClient mongoClient() { MyId id; UserWithComplexId userWithId; - @Before + @BeforeEach public void setUp() { repo.deleteAll(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index 5969d2b7f2..a3317dcb74 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -24,11 +24,9 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -39,14 +37,12 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.test.util.AfterTransactionAssertion; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.ReplSetClient; import org.springframework.lang.Nullable; import org.springframework.test.annotation.Rollback; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.transaction.AfterTransaction; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.transaction.annotation.Transactional; @@ -61,15 +57,13 @@ * @author Christoph Strobl * @currentRead Shadow's Edge - Brent Weeks */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) +@EnableIfReplicaSetAvailable @Transactional(transactionManager = "txManager") public class PersonRepositoryTransactionalTests { - public static @ClassRule RuleChain TEST_RULES = RuleChain.outerRule(MongoVersionRule.atLeast(Version.parse("3.7.3"))) - .around(ReplicaSet.required()); - static final String DB_NAME = "repository-tx-tests"; + static @ReplSetClient MongoClient mongoClient; @Configuration @EnableMongoRepositories @@ -77,7 +71,7 @@ static class Config extends AbstractMongoClientConfiguration { @Bean public MongoClient mongoClient() { - return MongoTestUtils.replSetClient(); + return mongoClient; } @Override @@ -101,7 +95,7 @@ MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { List>> assertionList; - @Before + @BeforeEach public void setUp() { assertionList = new CopyOnWriteArrayList<>(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index ae294d5eb6..9c08e352bd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -34,10 +34,10 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.reactivestreams.Publisher; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -61,12 +61,13 @@ import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactory; import org.springframework.data.mongodb.repository.support.SimpleReactiveMongoRepository; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor; import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.reactivestreams.client.MongoClient; @@ -76,10 +77,11 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class ReactiveMongoRepositoryTests { + static @Client MongoClient mongoClient; + @Autowired ReactiveMongoTemplate template; @Autowired ReactivePersonRepository repository; @@ -95,7 +97,7 @@ static class Config extends AbstractReactiveMongoConfiguration { @Bean @Override public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); + return mongoClient; } @Override @@ -131,16 +133,14 @@ ReactiveCappedCollectionRepository reactiveCappedCollectionRepository(ReactiveMo } } - @BeforeClass + @BeforeAll public static void cleanDb() { - MongoClient client = MongoTestUtils.reactiveClient(); - - MongoTestUtils.createOrReplaceCollectionNow("reactive", "person", client); - MongoTestUtils.createOrReplaceCollectionNow("reactive", "capped", client); + MongoTestUtils.createOrReplaceCollectionNow("reactive", "person", mongoClient); + MongoTestUtils.createOrReplaceCollectionNow("reactive", "capped", mongoClient); } - @Before + @BeforeEach public void setUp() throws Exception { repository.deleteAll().as(StepVerifier::create).verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java new file mode 100644 index 0000000000..86fed2409c --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java @@ -0,0 +1,32 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Christoph Strobl + */ +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Client { + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java index 9bd99945eb..418c23df59 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java @@ -22,6 +22,7 @@ import java.lang.annotation.Target; import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.extension.ExtendWith; /** * @author Christoph Strobl @@ -31,6 +32,7 @@ @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Tag("version-specific") +@ExtendWith(MongoServerCondition.class) public @interface EnableIfMongoServerVersion { /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java index 78f965ca85..eac3bf70b6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java @@ -22,6 +22,7 @@ import java.lang.annotation.Target; import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.extension.ExtendWith; /** * {@link EnableIfReplicaSetAvailable} marks a specific test class or method to be only executed against a server running in @@ -34,6 +35,7 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @Tag("replSet") +@ExtendWith(MongoServerCondition.class) public @interface EnableIfReplicaSetAvailable { } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java new file mode 100644 index 0000000000..3247cfe640 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java @@ -0,0 +1,176 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import static org.junit.platform.commons.util.AnnotationUtils.*; +import static org.junit.platform.commons.util.ReflectionUtils.*; + +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.function.Predicate; + +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.Extension; +import org.junit.jupiter.api.extension.ExtensionConfigurationException; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.junit.platform.commons.util.ExceptionUtils; +import org.junit.platform.commons.util.ReflectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ClassUtils; + +/** + * @author Christoph Strobl + */ +public class MongoClientExtension implements Extension, BeforeAllCallback, AfterAllCallback, ParameterResolver { + + private static final Logger LOGGER = LoggerFactory.getLogger(MongoClientExtension.class); + + private static final Namespace NAMESPACE = Namespace.create(MongoClientExtension.class); + private static final String SYNC_KEY = "mongo.client.sync"; + private static final String REACTIVE_KEY = "mongo.client.reactive"; + private static final String SYNC_REPLSET_KEY = "mongo.client.replset.sync"; + private static final String REACTIVE_REPLSET_KEY = "mongo.client.replset.reactive"; + + @Override + public void afterAll(ExtensionContext extensionContext) throws Exception { + closeClients(extensionContext); + } + + @Override + public void beforeAll(ExtensionContext context) throws Exception { + injectFields(context, null, ReflectionUtils::isStatic); + } + + private void injectFields(ExtensionContext context, Object testInstance, Predicate predicate) { + + findAnnotatedFields(context.getRequiredTestClass(), Client.class, predicate).forEach(field -> { + assertValidFieldCandidate(field); + try { + makeAccessible(field).set(testInstance, getMongoClient(field.getType(), context, false)); + } catch (Throwable t) { + ExceptionUtils.throwAsUncheckedException(t); + } + }); + + findAnnotatedFields(context.getRequiredTestClass(), ReplSetClient.class, predicate).forEach(field -> { + assertValidFieldCandidate(field); + try { + makeAccessible(field).set(testInstance, getMongoClient(field.getType(), context, true)); + } catch (Throwable t) { + ExceptionUtils.throwAsUncheckedException(t); + } + }); + } + + private Object getMongoClient(Class type, ExtensionContext extensionContext, boolean replSet) { + + Store store = extensionContext.getStore(NAMESPACE); + + if (ClassUtils.isAssignable(com.mongodb.client.MongoClient.class, type)) { + + LOGGER.debug("Obtaining sync client from store."); + return store.getOrComputeIfAbsent(replSet ? SYNC_REPLSET_KEY : SYNC_KEY, it -> syncClient(replSet), + com.mongodb.client.MongoClient.class); + } + + if (ClassUtils.isAssignable(com.mongodb.reactivestreams.client.MongoClient.class, type)) { + + LOGGER.debug("Obtaining reactive client from store."); + return store.getOrComputeIfAbsent(replSet ? REACTIVE_REPLSET_KEY : REACTIVE_KEY, key -> reactiveClient(replSet), + com.mongodb.reactivestreams.client.MongoClient.class); + } + + throw new IllegalStateException("Damn - something went wrong."); + } + + private com.mongodb.reactivestreams.client.MongoClient reactiveClient(boolean replSet) { + + LOGGER.debug("Creating new reactive {}client.", replSet ? "replica set " : ""); + return replSet ? MongoTestUtils.reactiveReplSetClient() : MongoTestUtils.reactiveClient(); + } + + private com.mongodb.client.MongoClient syncClient(boolean replSet) { + + LOGGER.debug("Creating new sync {}client.", replSet ? "replica set " : ""); + return replSet ? MongoTestUtils.replSetClient() : MongoTestUtils.client(); + } + + private void assertValidFieldCandidate(Field field) { + + assertSupportedType("field", field.getType()); + if (isPrivate(field)) { + throw new ExtensionConfigurationException("@MongoClient field [" + field + "] must not be private."); + } + } + + private void assertSupportedType(String target, Class type) { + + if (type != com.mongodb.client.MongoClient.class && type != com.mongodb.reactivestreams.client.MongoClient.class) { + throw new ExtensionConfigurationException("Can only resolve @MongoClient " + target + " of type " + + com.mongodb.client.MongoClient.class.getName() + " or " + + com.mongodb.reactivestreams.client.MongoClient.class.getName() + " but was: " + type.getName()); + } + } + + private void closeClients(ExtensionContext extensionContext) { + + Store store = extensionContext.getStore(NAMESPACE); + + closeClient(store, SYNC_KEY); + closeClient(store, SYNC_REPLSET_KEY); + closeClient(store, REACTIVE_KEY); + closeClient(store, REACTIVE_REPLSET_KEY); + } + + private void closeClient(Store store, String key) { + + Closeable client = store.remove(key, Closeable.class); + if (client != null) { + + LOGGER.debug("Closing {} {}client.", key.contains("reactive") ? "reactive" : "sync", + key.contains("replset") ? "replset " : ""); + + try { + client.close(); + } catch (IOException e) { + // so what? + } + } + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return parameterContext.isAnnotated(Client.class) || parameterContext.isAnnotated(ReplSetClient.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + + Class parameterType = parameterContext.getParameter().getType(); + boolean replSet = parameterContext.getParameter().getAnnotation(ReplSetClient.class) != null; + return getMongoClient(parameterType, extensionContext, replSet); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 1c65d2d59a..77361606d7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -22,8 +22,11 @@ import java.util.List; import org.bson.Document; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; import org.springframework.data.mongodb.SpringDataMongoDB; import org.springframework.data.util.Version; +import org.springframework.util.ObjectUtils; import com.mongodb.ConnectionString; import com.mongodb.ReadPreference; @@ -41,7 +44,10 @@ */ public class MongoTestUtils { - public static final String CONNECTION_STRING = "mongodb://localhost:27017/?replicaSet=rs0&w=majority"; + private static final Environment ENV = new StandardEnvironment(); + private static final Duration DEFAULT_TIMEOUT = Duration.ofMillis(10); + + public static final String CONNECTION_STRING = "mongodb://127.0.0.1:27017/?replicaSet=rs0&w=majority"; private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/?w=majority"; @@ -53,7 +59,7 @@ public class MongoTestUtils { * @return new instance of {@link com.mongodb.client.MongoClient}. */ public static MongoClient client() { - return client("localhost", 27017); + return client("127.0.0.1", 27017); } public static MongoClient client(String host, int port) { @@ -68,7 +74,7 @@ public static MongoClient client(String host, int port) { * @return new instance of {@link com.mongodb.reactivestreams.client.MongoClient}. */ public static com.mongodb.reactivestreams.client.MongoClient reactiveClient() { - return reactiveClient("localhost", 27017); + return reactiveClient("127.0.0.1", 27017); } public static com.mongodb.reactivestreams.client.MongoClient reactiveClient(String host, int port) { @@ -93,16 +99,13 @@ public static MongoCollection createOrReplaceCollection(String dbName, boolean collectionExists = database.listCollections().filter(new Document("name", collectionName)).first() != null; if (collectionExists) { + database.getCollection(collectionName).drop(); + giveTheServerALittleTimeToThink(); } database.createCollection(collectionName); - - try { - Thread.sleep(10); // server replication time - } catch (InterruptedException e) { - e.printStackTrace(); - } + giveTheServerALittleTimeToThink(); return database.getCollection(collectionName); } @@ -121,9 +124,9 @@ public static Mono createOrReplaceCollection(String dbName, String collect .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); return Mono.from(database.getCollection(collectionName).drop()) // - .delayElement(Duration.ofMillis(10)) // server replication time + .delayElement(getTimeout()) // server replication time .then(Mono.from(database.createCollection(collectionName))) // - .delayElement(Duration.ofMillis(10)); // server replication time + .delayElement(getTimeout()); // server replication time } /** @@ -157,7 +160,7 @@ public static void dropCollectionNow(String dbName, String collectionName, .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); Mono.from(database.getCollection(collectionName).drop()) // - .retryBackoff(3, Duration.ofMillis(250)) // + .delayElement(getTimeout()).retryBackoff(3, Duration.ofMillis(250)) // .as(StepVerifier::create) // .verifyComplete(); } @@ -177,7 +180,7 @@ public static void flushCollection(String dbName, String collectionName, .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); Mono.from(database.getCollection(collectionName).deleteMany(new Document())) // - .then() // + .delayElement(getTimeout()).then() // .as(StepVerifier::create) // .verifyComplete(); } @@ -231,4 +234,19 @@ public static boolean serverIsReplSet() { return false; } } + + public static Duration getTimeout() { + + return ObjectUtils.nullSafeEquals("jenkins", ENV.getProperty("user.name")) ? Duration.ofMillis(100) + : DEFAULT_TIMEOUT; + } + + private static void giveTheServerALittleTimeToThink() { + + try { + Thread.sleep(getTimeout().toMillis()); // server replication time + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java index 29596def07..ae81141cd2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoVersionRule.java @@ -54,7 +54,7 @@ public class MongoVersionRule implements TestRule { private final Version minVersion; private final Version maxVersion; - private String host = "localhost"; + private String host = "127.0.0.1"; private int port = 27017; public MongoVersionRule(Version min, Version max) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java new file mode 100644 index 0000000000..f64569b679 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java @@ -0,0 +1,32 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Christoph Strobl + */ +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ReplSetClient { + +} diff --git a/spring-data-mongodb/src/test/resources/geospatial.xml b/spring-data-mongodb/src/test/resources/geospatial.xml index 340be93c6d..8937e8f753 100644 --- a/spring-data-mongodb/src/test/resources/geospatial.xml +++ b/spring-data-mongodb/src/test/resources/geospatial.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd"> - + @@ -17,6 +17,7 @@ + diff --git a/spring-data-mongodb/src/test/resources/infrastructure.xml b/spring-data-mongodb/src/test/resources/infrastructure.xml index 7bdb2708d1..500c44e2bf 100644 --- a/spring-data-mongodb/src/test/resources/infrastructure.xml +++ b/spring-data-mongodb/src/test/resources/infrastructure.xml @@ -15,6 +15,7 @@ + diff --git a/spring-data-mongodb/src/test/resources/logback.xml b/spring-data-mongodb/src/test/resources/logback.xml index 5296a20451..5cfaf97c01 100644 --- a/spring-data-mongodb/src/test/resources/logback.xml +++ b/spring-data-mongodb/src/test/resources/logback.xml @@ -12,6 +12,7 @@ --> + diff --git a/spring-data-mongodb/src/test/resources/reactive-infrastructure.xml b/spring-data-mongodb/src/test/resources/reactive-infrastructure.xml index 9bd7479755..896bb26812 100644 --- a/spring-data-mongodb/src/test/resources/reactive-infrastructure.xml +++ b/spring-data-mongodb/src/test/resources/reactive-infrastructure.xml @@ -15,6 +15,7 @@ + From 0b77906a831033b494212133fa87e35ec0193362 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 5 Feb 2020 10:01:06 +0100 Subject: [PATCH 0073/1381] DATAMONGO-2461 - Polishing. Extend Javadoc. Reformat code. Reduce log level to info. Refactor resource disposal to use Store.CloseableResource. Original pull request: #831. --- .travis.yml | 1 - .../ReactiveMongoDatabaseUtilsUnitTests.java | 3 +- .../ReactiveTransactionIntegrationTests.java | 6 +- .../config/AbstractIntegrationTests.java | 1 - ...iveMongoConfigurationIntegrationTests.java | 3 +- .../config/MongoClientNamespaceTests.java | 15 ++-- .../MongoDbFactoryParserIntegrationTests.java | 8 +- .../config/MongoNamespaceReplicaSetTests.java | 3 +- .../config/MongoParserIntegrationTests.java | 2 +- .../data/mongodb/core/ClientSessionTests.java | 2 + .../DefaultReactiveIndexOperationsTests.java | 14 ++-- .../core/DefaultScriptOperationsTests.java | 5 +- .../data/mongodb/core/MongoTemplateTests.java | 2 +- .../core/MongoTemplateTransactionTests.java | 2 + .../mongodb/core/MongoTemplateUnitTests.java | 6 +- .../core/MongoTemplateUpdateTests.java | 4 +- .../data/mongodb/core/PersonExample.java | 3 +- ...ersonWithVersionPropertyOfTypeInteger.java | 3 +- .../PersonWithVersionPropertyOfTypeLong.java | 4 +- .../core/QueryCursorPreparerUnitTests.java | 39 ++++----- ...tiveChangeStreamOperationSupportTests.java | 6 +- .../core/ReactiveClientSessionTests.java | 2 + .../core/ReactiveMongoTemplateTests.java | 2 +- ...ReactiveMongoTemplateTransactionTests.java | 2 + .../core/ReactiveMongoTemplateUnitTests.java | 3 +- ...iveSessionBoundMongoTemplateUnitTests.java | 3 +- .../aggregation/FacetOperationUnitTests.java | 25 +++--- .../GeoNearOperationUnitTests.java | 5 +- .../aggregation/ObjectOperatorsUnitTests.java | 7 +- .../ReactiveAggregationUnitTests.java | 28 +++---- .../core/aggregation/UserWithLikes.java | 6 +- .../DefaultDbRefResolverUnitTests.java | 4 +- .../MappingMongoConverterUnitTests.java | 3 +- .../core/convert/QueryMapperUnitTests.java | 8 +- .../core/geo/GeoJsonModuleUnitTests.java | 16 ++-- .../data/mongodb/core/geo/GeoJsonTests.java | 8 +- .../core/geo/GeoSpatial2DSphereTests.java | 1 - ...entEntityIndexCreatorIntegrationTests.java | 5 +- ...ersistentEntityIndexResolverUnitTests.java | 3 +- .../data/mongodb/core/index/SampleEntity.java | 6 +- .../mongodb/core/index/TextIndexTests.java | 3 - .../data/mongodb/core/mapping/Account.java | 1 - .../data/mongodb/core/mapping/Address.java | 3 +- .../data/mongodb/core/mapping/BasePerson.java | 3 +- .../mapping/CustomCollectionWithIndex.java | 6 +- .../mapping/DetectedCollectionWithIndex.java | 6 +- .../mongodb/core/mapping/GeneratedId.java | 8 +- .../mongodb/core/mapping/GeoIndexedTests.java | 2 +- .../mongodb/core/mapping/GeoLocation.java | 8 +- .../data/mongodb/core/mapping/Location.java | 1 - ...PersistentPropertyComparatorUnitTests.java | 9 +-- .../data/mongodb/core/mapping/Person.java | 17 ++-- .../core/mapping/PersonCustomCollection1.java | 3 +- .../core/mapping/PersonCustomCollection2.java | 3 +- .../core/mapping/PersonMapProperty.java | 1 - .../core/mapping/PersonNullProperties.java | 8 +- .../mongodb/core/mapping/PersonWithDbRef.java | 1 - .../mongodb/core/mapping/PrimitiveId.java | 4 +- .../event/ApplicationContextEventTests.java | 3 +- .../data/mongodb/core/mapping/event/User.java | 6 +- .../core/messaging/ChangeStreamTests.java | 2 + .../messaging/CursorReadingTaskUnitTests.java | 3 +- .../DefaultMessageListenerContainerTests.java | 11 ++- .../mongodb/core/query/CriteriaTests.java | 2 +- .../mongodb/core/query/TextQueryTests.java | 7 +- .../data/mongodb/core/query/UpdateTests.java | 3 +- .../schema/JsonSchemaObjectUnitTests.java | 2 + .../data/mongodb/repository/Contact.java | 3 +- .../mongodb/repository/ContactRepository.java | 2 - .../data/mongodb/repository/Credentials.java | 1 - .../mongodb/repository/PersonAggregate.java | 1 - .../PersonRepositoryTransactionalTests.java | 2 + ...RepositoriesRegistrarIntegrationTests.java | 3 +- .../query/AbstractMongoQueryUnitTests.java | 5 +- .../ReactiveMongoQueryExecutionUnitTests.java | 5 +- ...eactiveStringBasedMongoQueryUnitTests.java | 4 +- ...nsuringQueryCreationListenerUnitTests.java | 3 +- .../QuerydslRepositorySupportTests.java | 10 +-- ...veQuerydslMongoPredicateExecutorTests.java | 3 +- .../SimpleMongoRepositoryUnitTests.java | 3 +- ...impleReactiveMongoRepositoryUnitTests.java | 3 +- ...veMongoRepositoryVersionedEntityTests.java | 2 +- .../data/mongodb/test/util/Client.java | 10 +++ .../test/util/EnableIfMongoServerVersion.java | 4 + .../util/EnableIfReplicaSetAvailable.java | 4 +- .../test/util/MongoClientExtension.java | 79 ++++++++++++------- .../data/mongodb/test/util/ReplSetClient.java | 7 ++ .../src/test/resources/logback.xml | 2 +- 88 files changed, 280 insertions(+), 271 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc732f61e6..30fcd9ca29 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ env: - MONGO_VERSION=4.2.0 - MONGO_VERSION=4.0.14 - MONGO_VERSION=3.6.16 - - MONGO_VERSION=3.4.23 global: - PROFILE=ci diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java index fb3d11b7bc..9a46ff82af 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import reactor.core.publisher.Mono; @@ -27,6 +27,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.transaction.reactive.TransactionSynchronizationManager; import org.springframework.transaction.reactive.TransactionalOperator; import org.springframework.transaction.support.DefaultTransactionDefinition; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index b472e1c9a7..61f9bdf9f0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -18,7 +18,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; -import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -32,6 +31,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIfSystemProperty; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -42,8 +42,8 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; -import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.reactive.TransactionalOperator; @@ -57,7 +57,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@ExtendWith({ MongoServerCondition.class, MongoClientExtension.class }) +@ExtendWith(MongoClientExtension.class) @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") @EnableIfReplicaSetAvailable @DisabledIfSystemProperty(named = "user.name", matches = "jenkins") diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 92e8ed602d..345551a195 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -33,7 +33,6 @@ import com.mongodb.MongoException; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java index 5bf0c189fe..e7c09ad2e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationIntegrationTests.java @@ -20,18 +20,17 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; -import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * Integration tests for {@link AbstractReactiveMongoConfiguration}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java index 88e3cb9920..075980c085 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java @@ -51,8 +51,7 @@ public class MongoClientNamespaceTests { public void clientWithJustHostAndPort() { assertThat(ctx.containsBean("client-with-just-host-port")).isTrue(); - MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-just-host-port", - MongoClientFactoryBean.class); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-just-host-port", MongoClientFactoryBean.class); assertThat(getField(factoryBean, "host")).isEqualTo("127.0.0.1"); assertThat(getField(factoryBean, "port")).isEqualTo(27017); @@ -66,8 +65,7 @@ public void clientWithJustHostAndPort() { public void clientWithConnectionString() { assertThat(ctx.containsBean("client-with-connection-string")).isTrue(); - MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-connection-string", - MongoClientFactoryBean.class); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-connection-string", MongoClientFactoryBean.class); assertThat(getField(factoryBean, "host")).isNull(); assertThat(getField(factoryBean, "port")).isNull(); @@ -82,8 +80,7 @@ public void clientWithConnectionString() { public void clientWithReplicaSet() { assertThat(ctx.containsBean("client-with-replica-set")).isTrue(); - MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-replica-set", - MongoClientFactoryBean.class); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-replica-set", MongoClientFactoryBean.class); assertThat(getField(factoryBean, "host")).isNull(); assertThat(getField(factoryBean, "port")).isNull(); @@ -112,8 +109,7 @@ public void clientWithCredential() { public void clientWithClusterSettings() { assertThat(ctx.containsBean("client-with-cluster-settings")).isTrue(); - MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-cluster-settings", - MongoClientFactoryBean.class); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-cluster-settings", MongoClientFactoryBean.class); MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); @@ -146,8 +142,7 @@ public void clientWithConnectionPoolSettings() { public void clientWithUUidSettings() { assertThat(ctx.containsBean("client-with-uuid-settings")).isTrue(); - MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-uuid-settings", - MongoClientFactoryBean.class); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-uuid-settings", MongoClientFactoryBean.class); MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); assertThat(settings.getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 1e03c7d280..51c8aefd65 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -17,9 +17,9 @@ import static org.assertj.core.api.Assertions.*; -import com.mongodb.client.MongoClient; import org.junit.Before; import org.junit.Test; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; @@ -36,6 +36,7 @@ import com.mongodb.ConnectionString; import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; /** @@ -59,9 +60,8 @@ public void setUp() { @Test // DATAMONGO-2199 public void testWriteConcern() throws Exception { - try(MongoClient client = MongoTestUtils.client()) { - SimpleMongoClientDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(client, - "database"); + try (MongoClient client = MongoTestUtils.client()) { + SimpleMongoClientDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(client, "database"); dbFactory.setWriteConcern(WriteConcern.ACKNOWLEDGED); dbFactory.getMongoDatabase(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java index f04cf44f11..b734bf2f6d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java @@ -22,11 +22,11 @@ import java.util.ArrayList; import java.util.List; -import com.mongodb.MongoClientSettings; import org.bson.Document; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.core.MongoClientFactoryBean; @@ -35,6 +35,7 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; +import com.mongodb.MongoClientSettings; import com.mongodb.ServerAddress; import com.mongodb.client.MongoClient; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java index 7d37e256f7..f37eb7ebd1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java @@ -19,7 +19,6 @@ import java.util.List; -import com.mongodb.client.MongoClient; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -33,6 +32,7 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; +import com.mongodb.client.MongoClient; /** * Integration tests for {@link MongoClientParser}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index 5c2ab969a4..eac80d7c79 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -29,6 +29,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -45,6 +46,7 @@ */ @ExtendWith({ MongoClientExtension.class }) @EnableIfReplicaSetAvailable +@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public class ClientSessionTests { private static final String DB_NAME = "client-session-tests"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index 816c5d03ba..1f4dd31fa9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -28,6 +28,7 @@ import org.junit.Before; 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.domain.Sort.Direction; @@ -45,7 +46,6 @@ import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; import com.mongodb.reactivestreams.client.MongoCollection; /** @@ -146,7 +146,8 @@ public void shouldApplyPartialFilterCorrectly() { indexOps.getIndexInfo().filter(this.indexByName("partial-with-criteria")).as(StepVerifier::create) // .consumeNextWith(indexInfo -> { - assertThat(Document.parse(indexInfo.getPartialFilterExpression())).isEqualTo(Document.parse("{ \"q-t-y\" : { \"$gte\" : 10 } }")); + assertThat(Document.parse(indexInfo.getPartialFilterExpression())) + .isEqualTo(Document.parse("{ \"q-t-y\" : { \"$gte\" : 10 } }")); }) // .verifyComplete(); } @@ -163,7 +164,8 @@ public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { indexOps.getIndexInfo().filter(this.indexByName("partial-with-mapped-criteria")).as(StepVerifier::create) // .consumeNextWith(indexInfo -> { - assertThat(Document.parse(indexInfo.getPartialFilterExpression())).isEqualTo(Document.parse("{ \"qty\" : { \"$gte\" : 10 } }")); + assertThat(Document.parse(indexInfo.getPartialFilterExpression())) + .isEqualTo(Document.parse("{ \"qty\" : { \"$gte\" : 10 } }")); }).verifyComplete(); } @@ -179,7 +181,8 @@ public void shouldApplyPartialDBOFilterCorrectly() { indexOps.getIndexInfo().filter(this.indexByName("partial-with-dbo")).as(StepVerifier::create) // .consumeNextWith(indexInfo -> { - assertThat(Document.parse(indexInfo.getPartialFilterExpression())).isEqualTo(Document.parse("{ \"qty\" : { \"$gte\" : 10 } }")); + assertThat(Document.parse(indexInfo.getPartialFilterExpression())) + .isEqualTo(Document.parse("{ \"qty\" : { \"$gte\" : 10 } }")); }) // .verifyComplete(); @@ -201,7 +204,8 @@ public void shouldFavorExplicitMappingHintViaClass() { indexOps.getIndexInfo().filter(this.indexByName("partial-with-inheritance")).as(StepVerifier::create) // .consumeNextWith(indexInfo -> { - assertThat(Document.parse(indexInfo.getPartialFilterExpression())).isEqualTo(Document.parse("{ \"a_g_e\" : { \"$gte\" : 10 } }")); + assertThat(Document.parse(indexInfo.getPartialFilterExpression())) + .isEqualTo(Document.parse("{ \"a_g_e\" : { \"$gte\" : 10 } }")); }) // .verifyComplete(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java index 11af0f65a0..a212e50416 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,9 +35,9 @@ import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoClient; -import org.springframework.test.context.junit.jupiter.SpringExtension; /** * Integration tests for {@link DefaultScriptOperations}. @@ -45,7 +46,7 @@ * @author Oliver Gierke * @since 1.7 */ -@ExtendWith({MongoClientExtension.class, SpringExtension.class}) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @EnableIfMongoServerVersion(isLessThan = "4.1.0") @ContextConfiguration public class DefaultScriptOperationsTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 179363302d..24e3feeaf8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -20,7 +20,6 @@ import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.core.query.Update.*; -import com.mongodb.MongoClientSettings; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -46,6 +45,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.convert.converter.Converter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index ebc07dc146..0c2ae519b1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -39,6 +39,7 @@ import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.test.util.AfterTransactionAssertion; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.ReplSetClient; @@ -60,6 +61,7 @@ */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @EnableIfReplicaSetAvailable +@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") @ContextConfiguration @Transactional(transactionManager = "txManager") public class MongoTemplateTransactionTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 31ca013cdb..c86eec5894 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -19,7 +19,6 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.*; -import com.mongodb.MongoClientSettings; import lombok.Data; import java.math.BigInteger; @@ -47,6 +46,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; + import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; @@ -97,6 +97,7 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; +import com.mongodb.MongoClientSettings; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.ReadPreference; @@ -164,7 +165,8 @@ public void beforeEach() { when(db.runCommand(any(), any(Class.class))).thenReturn(commandResultDocument); when(collection.find(any(org.bson.Document.class), any(Class.class))).thenReturn(findIterable); when(collection.mapReduce(any(), any(), eq(Document.class))).thenReturn(mapReduceIterable); - when(collection.countDocuments(any(Bson.class), any(CountOptions.class))).thenReturn(1L); // TODO: MongoDB 4 - fix me + when(collection.countDocuments(any(Bson.class), any(CountOptions.class))).thenReturn(1L); // TODO: MongoDB 4 - fix + // me when(collection.getNamespace()).thenReturn(new MongoNamespace("db.mock-collection")); when(collection.aggregate(any(List.class), any())).thenReturn(aggregateIterable); when(collection.withReadPreference(any())).thenReturn(collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index f0cb095bd2..bb777b2c1a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Version; import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; @@ -41,7 +42,6 @@ import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.MongoClientExtension; -import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; import com.mongodb.client.MongoClient; @@ -50,7 +50,7 @@ /** * @author Christoph Strobl */ -@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) +@ExtendWith({ MongoClientExtension.class }) class MongoTemplateUpdateTests { static final String DB_NAME = "update-test"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java index bab760d69b..8252b1977c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java @@ -34,7 +34,8 @@ public class PersonExample { @Autowired private MongoOperations mongoOps; public static void main(String[] args) { - AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersonExampleAppConfig.class); + AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext( + PersonExampleAppConfig.class); PersonExample example = applicationContext.getBean(PersonExample.class); example.doWork(); applicationContext.close(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java index de260326e2..71b491ff75 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeInteger.java @@ -23,8 +23,7 @@ public class PersonWithVersionPropertyOfTypeInteger { String firstName; int age; - @Version - Integer version; + @Version Integer version; @Override public String toString() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java index d55718dd7b..c201117458 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonWithVersionPropertyOfTypeLong.java @@ -27,7 +27,7 @@ public class PersonWithVersionPropertyOfTypeLong { @Override public String toString() { - return "PersonWithVersionPropertyOfTypeLong [id=" + id + ", firstName=" + firstName + ", age=" + age - + ", version=" + version + "]"; + return "PersonWithVersionPropertyOfTypeLong [id=" + id + ", firstName=" + firstName + ", age=" + age + ", version=" + + version + "]"; } } 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 c36fbd4235..7e5951f793 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 @@ -21,19 +21,20 @@ import java.util.concurrent.TimeUnit; -import com.mongodb.MongoClientSettings; import org.bson.Document; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Query; +import com.mongodb.MongoClientSettings; import com.mongodb.client.FindIterable; /** @@ -91,16 +92,16 @@ public void appliesDocumentHintsCorrectly() { } // TODO -// @Test // DATAMONGO-957 -// public void doesNotApplyMetaWhenEmpty() { -// -// Query query = query(where("foo").is("bar")); -// query.setMeta(new Meta()); -// -// prepare(query); -// -// verify(cursor, never()).modifiers(any(Document.class)); -// } + // @Test // DATAMONGO-957 + // public void doesNotApplyMetaWhenEmpty() { + // + // Query query = query(where("foo").is("bar")); + // query.setMeta(new Meta()); + // + // prepare(query); + // + // verify(cursor, never()).modifiers(any(Document.class)); + // } // @Test // DATAMONGO-957 // public void appliesMaxScanCorrectly() { @@ -130,14 +131,14 @@ public void appliesCommentCorrectly() { } // TODO -// @Test // DATAMONGO-957 -// public void appliesSnapshotCorrectly() { -// -// Query query = query(where("foo").is("bar")).useSnapshot(); -// prepare(query); -// -// verify(cursor).snapshot(true); -// } + // @Test // DATAMONGO-957 + // public void appliesSnapshotCorrectly() { + // + // Query query = query(where("foo").is("bar")).useSnapshot(); + // prepare(query); + // + // verify(cursor).snapshot(true); + // } @Test // DATAMONGO-1480 public void appliesNoCursorTimeoutCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java index 4869983fa1..f76a9e4f85 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportTests.java @@ -19,7 +19,6 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import lombok.SneakyThrows; -import org.springframework.data.mongodb.test.util.ReplSetClient; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; @@ -34,10 +33,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.data.mongodb.test.util.Client; + +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.ReplSetClient; import com.mongodb.reactivestreams.client.MongoClient; @@ -104,6 +105,7 @@ public void changeStreamEventsShouldBeEmittedCorrectly() { } @Test // DATAMONGO-1803 + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedException { BlockingQueue> documents = new LinkedBlockingQueue<>(100); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java index 3ee00c6931..5feac83d39 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java @@ -31,6 +31,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -135,6 +136,7 @@ public void addsClientSessionToContext() { } @Test // DATAMONGO-2001 + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void countInTransactionShouldReturnCount() { ClientSession session = Mono diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index 38f9d0d03d..571f1d875e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -24,7 +24,6 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Wither; -import org.junit.Rule; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -52,6 +51,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java index ce81645e8b..a92675dad1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java @@ -33,6 +33,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -50,6 +51,7 @@ */ @ExtendWith(MongoClientExtension.class) @EnableIfReplicaSetAvailable +@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public class ReactiveMongoTemplateTransactionTests { static final String DATABASE_NAME = "reactive-template-tx-tests"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 82ee812651..f48d81bb62 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; -import com.mongodb.MongoClientSettings; import lombok.Data; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -46,6 +45,7 @@ import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import org.reactivestreams.Publisher; + import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.support.StaticApplicationContext; @@ -77,6 +77,7 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; +import com.mongodb.MongoClientSettings; import com.mongodb.ReadPreference; import com.mongodb.client.model.CountOptions; import com.mongodb.client.model.CreateCollectionOptions; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java index bb63134515..183772b436 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java @@ -111,7 +111,8 @@ public void setUp() { when(collection.deleteMany(any(ClientSession.class), any(), any())).thenReturn(resultPublisher); when(collection.insertOne(any(ClientSession.class), any(Document.class))).thenReturn(resultPublisher); when(collection.aggregate(any(ClientSession.class), anyList(), any(Class.class))).thenReturn(aggregatePublisher); - when(collection.countDocuments(any(ClientSession.class), any(), any(CountOptions.class))).thenReturn(resultPublisher); + when(collection.countDocuments(any(ClientSession.class), any(), any(CountOptions.class))) + .thenReturn(resultPublisher); when(collection.drop(any(ClientSession.class))).thenReturn(resultPublisher); when(collection.findOneAndUpdate(any(ClientSession.class), any(), any(Bson.class), any())) .thenReturn(resultPublisher); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java index 23a630115f..be2ca5b26c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FacetOperationUnitTests.java @@ -66,13 +66,12 @@ public void shouldRenderEmpty() { @Test(expected = IllegalArgumentException.class) // DATAMONGO-1552 public void shouldRejectNonExistingFields() { - FacetOperation facetOperation = new FacetOperation() - .and(project("price"), // - bucket("price") // - .withBoundaries(0, 150, 200, 300, 400) // - .withDefaultBucket("Other") // - .andOutputCount().as("count") // - .andOutput("title").push().as("titles")) // + FacetOperation facetOperation = new FacetOperation().and(project("price"), // + bucket("price") // + .withBoundaries(0, 150, 200, 300, 400) // + .withDefaultBucket("Other") // + .andOutputCount().as("count") // + .andOutput("title").push().as("titles")) // .as("categorizedByPrice"); Document agg = facetOperation.toDocument(Aggregation.DEFAULT_CONTEXT); @@ -87,18 +86,16 @@ public void shouldRejectNonExistingFields() { @Test // DATAMONGO-1552 public void shouldHonorProjectedFields() { - FacetOperation facetOperation = new FacetOperation() - .and(project("price").and("title").as("name"), // - bucketAuto("price", 5) // - .andOutput("name").push().as("titles")) // + FacetOperation facetOperation = new FacetOperation().and(project("price").and("title").as("name"), // + bucketAuto("price", 5) // + .andOutput("name").push().as("titles")) // .as("categorizedByPrice"); Document agg = facetOperation.toDocument(Aggregation.DEFAULT_CONTEXT); assertThat(agg).isEqualTo(Document.parse("{ $facet: { categorizedByPrice: [" - + "{ $project: { price: 1, name: \"$title\" } }, " - + "{ $bucketAuto: { buckets: 5, groupBy: \"$price\", " - + "output: { titles: { $push: \"$name\" } } } } ] } }")); + + "{ $project: { price: 1, name: \"$title\" } }, " + "{ $bucketAuto: { buckets: 5, groupBy: \"$price\", " + + "output: { titles: { $push: \"$name\" } } } } ] } }")); } @Test // DATAMONGO-1553 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java index bac532834b..2fe72368a5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java @@ -108,8 +108,9 @@ public void rendersIndexKey() { NearQuery query = NearQuery.near(10.0, 20.0); - assertThat(new GeoNearOperation(query, "distance").useIndex("index-1").toPipelineStages(Aggregation.DEFAULT_CONTEXT)) - .containsExactly($geoNear().near(10.0, 20.0).key("index-1").doc()); + assertThat( + new GeoNearOperation(query, "distance").useIndex("index-1").toPipelineStages(Aggregation.DEFAULT_CONTEXT)) + .containsExactly($geoNear().near(10.0, 20.0).key("index-1").doc()); } @Test // DATAMONGO-2264 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java index 0f15531b52..0742ac937f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java @@ -67,10 +67,9 @@ public void mergeMuliFieldReference() { @Test // DATAMONGO-2053 public void mergeMixed() { - assertThat( - ObjectOperators.valueOf("kettricken").mergeWithValuesOf(EXPRESSION).mergeWithValuesOf("verity") - .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( - Document.parse("{ $mergeObjects: [ \"$kettricken\", " + EXPRESSION_STRING + ", \"$verity\" ] } ")); + assertThat(ObjectOperators.valueOf("kettricken").mergeWithValuesOf(EXPRESSION).mergeWithValuesOf("verity") + .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( + Document.parse("{ $mergeObjects: [ \"$kettricken\", " + EXPRESSION_STRING + ", \"$verity\" ] } ")); } @Test // DATAMONGO-2053 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java index 7440fbd232..b83480de06 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java @@ -86,12 +86,10 @@ public void shouldHandleMissingEntityClass() { @Test // DATAMONGO-1646 public void errorsOnExplainUsage() { - assertThatIllegalArgumentException().isThrownBy(() -> template - .aggregate(newAggregation(Product.class, // - project("name", "netPrice")) // - .withOptions(AggregationOptions.builder().explain(true).build()), - INPUT_COLLECTION, TagCount.class) - .subscribe()); + assertThatIllegalArgumentException().isThrownBy(() -> template.aggregate(newAggregation(Product.class, // + project("name", "netPrice")) // + .withOptions(AggregationOptions.builder().explain(true).build()), + INPUT_COLLECTION, TagCount.class).subscribe()); } @Test // DATAMONGO-1646, DATAMONGO-1311 @@ -111,10 +109,9 @@ public void appliesBatchSizeWhenPresent() { @Test // DATAMONGO-1646 public void appliesCollationCorrectlyWhenPresent() { - template.aggregate( - newAggregation(Product.class, // - project("name", "netPrice")) // - .withOptions(AggregationOptions.builder().collation(Collation.of("en_US")).build()), + template.aggregate(newAggregation(Product.class, // + project("name", "netPrice")) // + .withOptions(AggregationOptions.builder().collation(Collation.of("en_US")).build()), INPUT_COLLECTION, TagCount.class).subscribe(); verify(publisher).collation(eq(com.mongodb.client.model.Collation.builder().locale("en_US").build())); @@ -134,13 +131,10 @@ public void doesNotSetCollationWhenNotPresent() { @Test // DATAMONGO-1646 public void appliesDiskUsageCorrectly() { - template - .aggregate( - newAggregation(Product.class, // - project("name", "netPrice")) // - .withOptions(AggregationOptions.builder().allowDiskUse(true).build()), - INPUT_COLLECTION, TagCount.class) - .subscribe(); + template.aggregate(newAggregation(Product.class, // + project("name", "netPrice")) // + .withOptions(AggregationOptions.builder().allowDiskUse(true).build()), + INPUT_COLLECTION, TagCount.class).subscribe(); verify(publisher).allowDiskUse(eq(true)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java index 3d4aecda59..57ad29c438 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UserWithLikes.java @@ -15,14 +15,14 @@ */ package org.springframework.data.mongodb.core.aggregation; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.Set; -import lombok.Data; -import lombok.NoArgsConstructor; - /** * @author Thomas Darimont * @author Christoph Strobl diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index 639ca4afc2..8cb3852427 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -16,8 +16,7 @@ package org.springframework.data.mongodb.core.convert; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.Arrays; @@ -32,6 +31,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 5fdd8e185d..e2a8e12c3d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -20,7 +20,6 @@ import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.DocumentTestUtils.*; -import com.mongodb.DBObject; import lombok.EqualsAndHashCode; import lombok.RequiredArgsConstructor; @@ -42,6 +41,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.factory.annotation.Value; @@ -80,6 +80,7 @@ import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; import com.mongodb.DBRef; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 9f00affefd..e3ab12d40c 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -28,8 +28,6 @@ import java.util.Map; import java.util.Optional; -import com.mongodb.MongoClientSettings; -import com.mongodb.client.model.Filters; import org.bson.conversions.Bson; import org.bson.types.Code; import org.bson.types.ObjectId; @@ -38,6 +36,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -60,6 +59,8 @@ import org.springframework.data.mongodb.core.query.Query; import com.mongodb.BasicDBObject; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.model.Filters; /** * Unit tests for {@link QueryMapper}. @@ -180,7 +181,8 @@ void handlesEnumsInNotEqualCorrectly() { @Test // DATAMONGO-373 void handlesNativelyBuiltQueryCorrectly() { - Bson query = new BasicDBObject(Filters.or(new BasicDBObject("foo", "bar")).toBsonDocument(org.bson.Document.class, MongoClientSettings.getDefaultCodecRegistry())); + Bson query = new BasicDBObject(Filters.or(new BasicDBObject("foo", "bar")).toBsonDocument(org.bson.Document.class, + MongoClientSettings.getDefaultCodecRegistry())); mapper.getMappedObject(query, Optional.empty()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java index 559b07b482..32c6287dac 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java @@ -52,8 +52,8 @@ public void shouldDeserializeJsonPointCorrectly() throws JsonParseException, Jso } @Test // DATAMONGO-1181 - public void shouldDeserializeGeoJsonLineStringCorrectly() throws JsonParseException, JsonMappingException, - IOException { + public void shouldDeserializeGeoJsonLineStringCorrectly() + throws JsonParseException, JsonMappingException, IOException { String json = "{ \"type\": \"LineString\", \"coordinates\": [ [10.0, 20.0], [30.0, 40.0], [50.0, 60.0] ]}"; @@ -62,8 +62,8 @@ public void shouldDeserializeGeoJsonLineStringCorrectly() throws JsonParseExcept } @Test // DATAMONGO-1181 - public void shouldDeserializeGeoJsonMultiPointCorrectly() throws JsonParseException, JsonMappingException, - IOException { + public void shouldDeserializeGeoJsonMultiPointCorrectly() + throws JsonParseException, JsonMappingException, IOException { String json = "{ \"type\": \"MultiPoint\", \"coordinates\": [ [10.0, 20.0], [30.0, 40.0], [50.0, 60.0] ]}"; @@ -73,8 +73,8 @@ public void shouldDeserializeGeoJsonMultiPointCorrectly() throws JsonParseExcept @Test // DATAMONGO-1181 @SuppressWarnings("unchecked") - public void shouldDeserializeGeoJsonMultiLineStringCorrectly() throws JsonParseException, JsonMappingException, - IOException { + public void shouldDeserializeGeoJsonMultiLineStringCorrectly() + throws JsonParseException, JsonMappingException, IOException { String json = "{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [10.0, 20.0], [30.0, 40.0] ], [ [50.0, 60.0] , [70.0, 80.0] ] ]}"; @@ -92,8 +92,8 @@ public void shouldDeserializeGeoJsonPolygonCorrectly() throws JsonParseException } @Test // DATAMONGO-1181 - public void shouldDeserializeGeoJsonMultiPolygonCorrectly() throws JsonParseException, JsonMappingException, - IOException { + public void shouldDeserializeGeoJsonMultiPolygonCorrectly() + throws JsonParseException, JsonMappingException, IOException { String json = "{ \"type\": \"Polygon\", \"coordinates\": [" + "[[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]]," diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index 3adc352e7a..ed9d941672 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -25,13 +25,11 @@ import java.util.List; import org.assertj.core.data.Percentage; -import org.junit.After; -import org.junit.Before; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; @@ -52,10 +50,8 @@ import org.springframework.data.mongodb.test.util.BasicDbListBuilder; import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.MongoClientExtension; -import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.WriteConcern; @@ -66,7 +62,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith({MongoClientExtension.class, SpringExtension.class}) +@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration public class GeoJsonTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java index 7eb7e6a82d..be8516ac2b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java @@ -22,7 +22,6 @@ import java.util.List; -import org.junit.Ignore; import org.junit.Test; import org.springframework.data.domain.Sort.Direction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java index 41a11f1728..40275a811f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java @@ -20,7 +20,6 @@ import java.util.Arrays; import java.util.List; -import com.mongodb.client.MongoClient; import org.hamcrest.core.IsInstanceOf; import org.junit.ClassRule; import org.junit.Rule; @@ -28,6 +27,7 @@ import org.junit.rules.ExpectedException; import org.junit.rules.RuleChain; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.DataIntegrityViolationException; @@ -46,6 +46,7 @@ import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoCommandException; +import com.mongodb.client.MongoClient; /** * Integration tests for {@link MongoPersistentEntityIndexCreator}. @@ -99,7 +100,7 @@ public void createIndexShouldThrowMeaningfulExceptionWhenIndexCreationFails() { expectedException.expectMessage("lastname"); expectedException.expectCause(IsInstanceOf. instanceOf(MongoCommandException.class)); - try(MongoClient client = MongoTestUtils.client()) { + try (MongoClient client = MongoTestUtils.client()) { MongoTemplate mongoTemplate = new MongoTemplate(client, "issue"); MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(new MongoMappingContext(), diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 8089054d25..0c9f2e9a76 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -659,7 +659,8 @@ public void shouldIdentifyRepeatedAnnotationCorrectly() { assertThat(indexDefinitions).hasSize(2); assertIndexPathAndCollection(new String[] { "firstname", "lastname" }, "repeatedCompoundIndex", indexDefinitions.get(0)); - assertIndexPathAndCollection(new String[] { "address.city", "address.street" }, "repeatedCompoundIndex", indexDefinitions.get(1)); + assertIndexPathAndCollection(new String[] { "address.city", "address.street" }, "repeatedCompoundIndex", + indexDefinitions.get(1)); } @Document("CompoundIndexOnLevelOne") diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/SampleEntity.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/SampleEntity.java index a099c4cb08..e419a75012 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/SampleEntity.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/SampleEntity.java @@ -6,9 +6,7 @@ @Document public class SampleEntity { - @Id - String id; + @Id String id; - @Indexed - String prop; + @Indexed String prop; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java index ea592097a9..8f15f45831 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java @@ -20,7 +20,6 @@ import java.util.List; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -31,8 +30,6 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Language; import org.springframework.data.mongodb.core.query.Collation; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; import com.mongodb.WriteConcern; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java index 839becd04b..53afb52996 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Account.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.core.mapping; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java index 87e76e4886..12b1003759 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Address.java @@ -20,8 +20,7 @@ */ public class Address implements Comparable

      { - @SuppressWarnings("unused") - private String id; + @SuppressWarnings("unused") private String id; private String[] lines; private String city; private String provinceOrState; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java index 1b0e43c38e..16d9ae7764 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasePerson.java @@ -19,7 +19,8 @@ /** * {@link QuerySupertype} is necessary for Querydsl 2.2.0-beta4 to compile the query classes directly. Can be removed as - * soon as https://bugs.launchpad.net/querydsl/+bug/776219 is fixed. + * soon as https://bugs.launchpad.net/querydsl/+bug/776219 + * is fixed. * * @see https://bugs.launchpad.net/querydsl/+bug/776219 * @author Jon Brisbin diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java index d3db39006e..3cfbbb40a7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CustomCollectionWithIndex.java @@ -24,10 +24,8 @@ @Document("foobar") public class CustomCollectionWithIndex { - @Id - private String id; - @Indexed - private String name; + @Id private String id; + @Indexed private String name; public CustomCollectionWithIndex(String name) { this.name = name; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java index 7b993950aa..c5c05a341f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/DetectedCollectionWithIndex.java @@ -24,10 +24,8 @@ @Document public class DetectedCollectionWithIndex { - @Id - private String id; - @Indexed - private String name; + @Id private String id; + @Indexed private String name; public DetectedCollectionWithIndex(String name) { this.name = name; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java index 53ff50a866..3b809b63db 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeneratedId.java @@ -16,8 +16,8 @@ package org.springframework.data.mongodb.core.mapping; import org.bson.types.ObjectId; + import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin @@ -25,10 +25,8 @@ @Document public class GeneratedId { - @Id - private ObjectId id; - @SuppressWarnings("unused") - private String name; + @Id private ObjectId id; + @SuppressWarnings("unused") private String name; public GeneratedId(String name) { this.name = name; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java index b5fde7dd64..1bb99d347d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java @@ -66,7 +66,7 @@ public void cleanUp() { private void cleanDb() { - try(MongoClient mongo = MongoTestUtils.client()) { + try (MongoClient mongo = MongoTestUtils.client()) { MongoDatabase db = mongo.getDatabase(GeoIndexedAppConfig.GEO_DB); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java index d5f655a93c..d7bab10755 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoLocation.java @@ -16,9 +16,9 @@ package org.springframework.data.mongodb.core.mapping; import org.bson.types.ObjectId; + import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.GeoSpatialIndexed; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin @@ -26,10 +26,8 @@ @Document("geolocation") public class GeoLocation { - @Id - private ObjectId id; - @GeoSpatialIndexed - private double[] location; + @Id private ObjectId id; + @GeoSpatialIndexed private double[] location; public GeoLocation(double[] location) { this.location = location; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java index 685fb2f988..dd61555efa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Location.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.core.mapping; import org.bson.types.ObjectId; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java index cdc5fa9bd4..b0a013ae5f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java @@ -22,14 +22,11 @@ @RunWith(MockitoJUnitRunner.class) public class MongoPersistentPropertyComparatorUnitTests { - @Mock - MongoPersistentProperty firstName; + @Mock MongoPersistentProperty firstName; - @Mock - MongoPersistentProperty lastName; + @Mock MongoPersistentProperty lastName; - @Mock - MongoPersistentProperty ssn; + @Mock MongoPersistentProperty ssn; @Test public void ordersPropertiesCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java index efb0dc9b92..67b2f3f67c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/Person.java @@ -23,8 +23,6 @@ import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.index.CompoundIndexes; import org.springframework.data.mongodb.core.index.Indexed; -import org.springframework.data.mongodb.core.mapping.DBRef; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin @@ -33,18 +31,13 @@ @CompoundIndexes({ @CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}") }) public class Person { - @Id - private String id; - @Indexed(unique = true) - private Integer ssn; + @Id private String id; + @Indexed(unique = true) private Integer ssn; private String firstName; - @Indexed - private String lastName; + @Indexed private String lastName; private Integer age; - @Transient - private Integer accountTotal; - @DBRef - private List accounts; + @Transient private Integer accountTotal; + @DBRef private List accounts; private T address; public Person(Integer ssn) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java index 4ae87735b9..f007d664f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection1.java @@ -23,8 +23,7 @@ @Document("person1") public class PersonCustomCollection1 extends BasePerson { - @Id - private String id; + @Id private String id; public PersonCustomCollection1(Integer ssn, String firstName, String lastName) { super(ssn, firstName, lastName); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java index b6e78bfb9c..cd919d83c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonCustomCollection2.java @@ -23,8 +23,7 @@ @Document("person2") public class PersonCustomCollection2 extends BasePerson { - @Id - private String id; + @Id private String id; public PersonCustomCollection2(Integer ssn, String firstName, String lastName) { super(ssn, firstName, lastName); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java index 140122e494..7a310bf815 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonMapProperty.java @@ -18,7 +18,6 @@ import java.util.Map; import org.bson.types.ObjectId; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java index 98bcbe6c61..57a05a17db 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonNullProperties.java @@ -16,8 +16,8 @@ package org.springframework.data.mongodb.core.mapping; import org.bson.types.ObjectId; + import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin @@ -25,11 +25,9 @@ @Document public class PersonNullProperties extends BasePerson { - @Id - private ObjectId id; + @Id private ObjectId id; - public PersonNullProperties() { - } + public PersonNullProperties() {} public ObjectId getId() { return id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java index 1ecf7fe0e9..8875ac7320 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PersonWithDbRef.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.core.mapping; - /** * @author Jon Brisbin */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java index d2a6f8d9d0..dceb81de00 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/PrimitiveId.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.core.mapping; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; /** * @author Jon Brisbin @@ -24,8 +23,7 @@ @Document public class PrimitiveId { - @Id - int id; + @Id int id; String text; public PrimitiveId(Integer id) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java index 125ddf536c..28c9e53d5c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java @@ -28,10 +28,11 @@ import java.util.List; import java.util.Map; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.data.annotation.Id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java index 96bc28c76c..26b88c966b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/User.java @@ -26,11 +26,9 @@ */ public class User { - @Size(min = 10) - private String name; + @Size(min = 10) private String name; - @Min(18) - private Integer age; + @Min(18) private Integer age; public User(String name, Integer age) { this.name = name; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index 80eaac7ed7..216e765b97 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -48,6 +48,7 @@ import org.springframework.data.mongodb.core.messaging.SubscriptionUtils.*; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoVersion; @@ -387,6 +388,7 @@ public void readsOnlyDiffForUpdateWhenOptionsDeclareDefaultExplicitly() throws I } @Test // DATAMONGO-1803 + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecified() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java index 10527e30cd..c3f955a670 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java @@ -30,10 +30,11 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.data.mongodb.core.messaging.Task.State; +import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.util.ErrorHandler; import com.mongodb.ServerAddress; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index f0fdbfa246..52d2581b55 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -27,13 +27,10 @@ import java.util.stream.Collectors; import org.bson.Document; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; @@ -42,10 +39,10 @@ import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoServerCondition; -import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.util.ErrorHandler; import com.mongodb.client.MongoClient; @@ -58,7 +55,7 @@ * * @author Christoph Strobl */ -@ExtendWith({MongoClientExtension.class, MongoServerCondition.class}) +@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) public class DefaultMessageListenerContainerTests { public static final String DATABASE_NAME = "change-stream-events"; @@ -93,6 +90,7 @@ void beforeEach() { @Test // DATAMONGO-1803 @EnableIfReplicaSetAvailable + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void shouldCollectMappedChangeStreamMessagesCorrectly() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); @@ -355,6 +353,7 @@ public void runsMoreThanOneTaskAtOnce() throws InterruptedException { @Test // DATAMONGO-2012 @EnableIfReplicaSetAvailable + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void databaseLevelWatch() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java index ee1bf6dc8d..dc3e862be9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java @@ -19,7 +19,6 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; -import com.mongodb.client.MongoClients; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -31,6 +30,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; + import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java index 56860f6aad..d0b4b70823 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java @@ -24,7 +24,6 @@ import org.bson.Document; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -38,8 +37,6 @@ import org.springframework.data.mongodb.core.mapping.Language; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.query.TextQueryTests.FullTextDoc.FullTextDocBuilder; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; /** * @author Christoph Strobl @@ -201,8 +198,8 @@ public void shouldApplyPaginationCorrectly() { initWithDefaultDocuments(); // page 1 - List result = template - .find(new TextQuery("bake coffee cake").sortByScore().with(PageRequest.of(0, 2)), FullTextDoc.class); + List result = template.find(new TextQuery("bake coffee cake").sortByScore().with(PageRequest.of(0, 2)), + FullTextDoc.class); assertThat(result).hasSize(2); assertThat(result).containsExactly(BAKE, COFFEE); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java index a56f1a7d0f..aa8e857ae5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java @@ -479,8 +479,7 @@ public void toStringShouldPrettyPrintModifiers() { @Test // DATAMONGO-1777, DATAMONGO-2198 public void toStringConsidersIsolated() { - assertThat(new Update().set("key", "value").isolated().toString()) - .contains("\"$isolated\""); + assertThat(new Update().set("key", "value").isolated().toString()).contains("\"$isolated\""); } @Test // DATAMONGO-1778 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java index 3ee7a3a16b..fa98c5c735 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java @@ -18,6 +18,7 @@ import static org.springframework.data.domain.Range.from; import static org.springframework.data.domain.Range.Bound.*; import static org.springframework.data.mongodb.core.schema.JsonSchemaObject.*; +import static org.springframework.data.mongodb.core.schema.JsonSchemaObject.array; import static org.springframework.data.mongodb.core.schema.JsonSchemaObject.of; import static org.springframework.data.mongodb.test.util.Assertions.*; @@ -31,6 +32,7 @@ import org.bson.Document; import org.junit.Test; + import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.*; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java index 9c19645343..d3fda4c782 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java @@ -27,8 +27,7 @@ @Document public abstract class Contact { - @Id - protected String id; + @Id protected String id; public Contact() { this.id = new ObjectId().toString(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java index 27bef5f4ab..3efd8e7be7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ContactRepository.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.repository; -import org.springframework.data.mongodb.repository.MongoRepository; - /** * Simple repository interface managing {@link Contact}s. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java index ba66f34c43..5578879bff 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Credentials.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.repository; /** - * * @author Oliver Gierke */ public interface Credentials { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java index adbe6a1eb9..d2b83367fd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonAggregate.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.springframework.data.annotation.Id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index a3317dcb74..ad3e109437 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -37,6 +37,7 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.test.util.AfterTransactionAssertion; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.ReplSetClient; @@ -59,6 +60,7 @@ */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @EnableIfReplicaSetAvailable +@EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") @Transactional(transactionManager = "txManager") public class PersonRepositoryTransactionalTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java index b672180178..48c347906f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrarIntegrationTests.java @@ -18,6 +18,7 @@ import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -29,8 +30,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.reactivestreams.client.MongoClients; - /** * Integration tests for {@link ReactiveMongoRepositoriesRegistrar}. * 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 87e87d880c..175c6eeb4c 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 @@ -16,9 +16,7 @@ package org.springframework.data.mongodb.repository.query; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.lang.reflect.Method; @@ -35,6 +33,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java index 15f2c22854..e5591d0317 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java @@ -16,9 +16,7 @@ package org.springframework.data.mongodb.repository.query; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import reactor.core.publisher.Flux; @@ -34,6 +32,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.reactivestreams.Publisher; + import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Range; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java index 66396718b8..e6a263c7c3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java @@ -216,8 +216,8 @@ public void shouldSupportNonQuotedBinaryDataReplacement() throws Exception { ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAsBinary", byte[].class); org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); - org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { '$binary' : '" - + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + 0 + "'}}"); + org.springframework.data.mongodb.core.query.Query reference = new BasicQuery( + "{'lastname' : { '$binary' : '" + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + 0 + "'}}"); assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java index 48f8898347..c301b8a17c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.repository.support; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.mockito.Mockito.anyString; @@ -28,6 +28,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.index.IndexDefinition; import org.springframework.data.mongodb.core.index.IndexOperations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index a3337f4c3e..2fd7b284e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -272,14 +272,12 @@ public void toStringShouldRenderQuery() { .isEqualTo("find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}})"); query = query.orderBy(p.firstname.asc()); - assertThat(StringUtils.trimAllWhitespace(query.toString())) - .isEqualTo( - "find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}}).sort({\"firstname\":1})"); + assertThat(StringUtils.trimAllWhitespace(query.toString())).isEqualTo( + "find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}}).sort({\"firstname\":1})"); query = query.offset(1).limit(5); - assertThat(StringUtils.trimAllWhitespace(query.toString())) - .isEqualTo( - "find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}}).sort({\"firstname\":1}).skip(1).limit(5)"); + assertThat(StringUtils.trimAllWhitespace(query.toString())).isEqualTo( + "find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}}).sort({\"firstname\":1}).skip(1).limit(5)"); } @Data diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java index c714056358..e83d009aaa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.repository.support; -import org.springframework.data.mongodb.core.query.BasicQuery; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -39,6 +38,7 @@ import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.repository.Address; import org.springframework.data.mongodb.repository.Person; import org.springframework.data.mongodb.repository.QAddress; @@ -52,7 +52,6 @@ import com.mongodb.MongoException; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; import com.mongodb.reactivestreams.client.MongoDatabase; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java index 760b36157c..eaddc42b0a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.repository.support; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import org.junit.Before; @@ -25,6 +25,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.domain.Example; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java index bb0d648224..d283eedeab 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java @@ -32,7 +32,7 @@ package org.springframework.data.mongodb.repository.support; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import reactor.core.publisher.Flux; @@ -44,6 +44,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.data.domain.Example; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.ReactiveMongoOperations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java index 416e97194f..e727f61148 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java @@ -23,6 +23,7 @@ import org.junit.Before; 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.dao.OptimisticLockingFailureException; @@ -36,7 +37,6 @@ import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * @author Mark Paluch diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java index 86fed2409c..31dcb5d315 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Client.java @@ -21,12 +21,22 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ExtendWith; + /** + * Marks a field or method as to be autowired by JUnit's dependency injection facilities for injection of a MongoDB + * client instance. Depends on {@link MongoClientExtension}. + * * @author Christoph Strobl + * @see com.mongodb.client.MongoClient + * @see com.mongodb.reactivestreams.client.MongoClient + * @see ReplSetClient + * @see MongoClientExtension */ @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Documented +@ExtendWith(MongoClientExtension.class) public @interface Client { } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java index 418c23df59..9738969055 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfMongoServerVersion.java @@ -25,6 +25,10 @@ import org.junit.jupiter.api.extension.ExtendWith; /** + * {@code @EnableIfMongoServerVersion} is used to signal that the annotated test class or test method is only + * enabled if the value of the specified version boundaries {@link #isGreaterThanEqual()} and + * {@link #isLessThan()} match the connected MongoDB server version. + * * @author Christoph Strobl * @since 3.0 */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java index eac3bf70b6..fc01c65f93 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/EnableIfReplicaSetAvailable.java @@ -25,8 +25,8 @@ import org.junit.jupiter.api.extension.ExtendWith; /** - * {@link EnableIfReplicaSetAvailable} marks a specific test class or method to be only executed against a server running in - * replicaSet mode. Intended to be used along with {@link MongoServerCondition}. + * {@link EnableIfReplicaSetAvailable} marks a specific test class or method to be only executed against a server + * running in replicaSet mode. Intended to be used along with {@link MongoServerCondition}. * * @author Christoph Strobl * @since 3.0 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java index 3247cfe640..2da900ca09 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java @@ -19,7 +19,6 @@ import static org.junit.platform.commons.util.ReflectionUtils.*; import java.io.Closeable; -import java.io.IOException; import java.lang.reflect.Field; import java.util.function.Predicate; @@ -37,10 +36,17 @@ import org.junit.platform.commons.util.ReflectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.util.ClassUtils; +import com.mongodb.client.MongoClient; + /** + * JUnit {@link Extension} providing parameter resolution for synchronous and reactive MongoDB client instances. + * * @author Christoph Strobl + * @see Client + * @see ReplSetClient */ public class MongoClientExtension implements Extension, BeforeAllCallback, AfterAllCallback, ParameterResolver { @@ -53,9 +59,7 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After private static final String REACTIVE_REPLSET_KEY = "mongo.client.replset.reactive"; @Override - public void afterAll(ExtensionContext extensionContext) throws Exception { - closeClients(extensionContext); - } + public void afterAll(ExtensionContext extensionContext) throws Exception {} @Override public void beforeAll(ExtensionContext context) throws Exception { @@ -91,29 +95,29 @@ private Object getMongoClient(Class type, ExtensionContext extensionContext, LOGGER.debug("Obtaining sync client from store."); return store.getOrComputeIfAbsent(replSet ? SYNC_REPLSET_KEY : SYNC_KEY, it -> syncClient(replSet), - com.mongodb.client.MongoClient.class); + SyncClientHolder.class).client; } if (ClassUtils.isAssignable(com.mongodb.reactivestreams.client.MongoClient.class, type)) { LOGGER.debug("Obtaining reactive client from store."); return store.getOrComputeIfAbsent(replSet ? REACTIVE_REPLSET_KEY : REACTIVE_KEY, key -> reactiveClient(replSet), - com.mongodb.reactivestreams.client.MongoClient.class); + ReactiveClientHolder.class).client; } throw new IllegalStateException("Damn - something went wrong."); } - private com.mongodb.reactivestreams.client.MongoClient reactiveClient(boolean replSet) { + private ReactiveClientHolder reactiveClient(boolean replSet) { LOGGER.debug("Creating new reactive {}client.", replSet ? "replica set " : ""); - return replSet ? MongoTestUtils.reactiveReplSetClient() : MongoTestUtils.reactiveClient(); + return new ReactiveClientHolder(replSet ? MongoTestUtils.reactiveReplSetClient() : MongoTestUtils.reactiveClient()); } - private com.mongodb.client.MongoClient syncClient(boolean replSet) { + private SyncClientHolder syncClient(boolean replSet) { LOGGER.debug("Creating new sync {}client.", replSet ? "replica set " : ""); - return replSet ? MongoTestUtils.replSetClient() : MongoTestUtils.client(); + return new SyncClientHolder(replSet ? MongoTestUtils.replSetClient() : MongoTestUtils.client()); } private void assertValidFieldCandidate(Field field) { @@ -133,29 +137,11 @@ private void assertSupportedType(String target, Class type) { } } - private void closeClients(ExtensionContext extensionContext) { - - Store store = extensionContext.getStore(NAMESPACE); - - closeClient(store, SYNC_KEY); - closeClient(store, SYNC_REPLSET_KEY); - closeClient(store, REACTIVE_KEY); - closeClient(store, REACTIVE_REPLSET_KEY); - } - private void closeClient(Store store, String key) { Closeable client = store.remove(key, Closeable.class); if (client != null) { - LOGGER.debug("Closing {} {}client.", key.contains("reactive") ? "reactive" : "sync", - key.contains("replset") ? "replset " : ""); - - try { - client.close(); - } catch (IOException e) { - // so what? - } } } @@ -173,4 +159,41 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte boolean replSet = parameterContext.getParameter().getAnnotation(ReplSetClient.class) != null; return getMongoClient(parameterType, extensionContext, replSet); } + + static class SyncClientHolder implements Store.CloseableResource { + + final MongoClient client; + + public SyncClientHolder(MongoClient client) { + this.client = client; + } + + @Override + public void close() { + try { + client.close(); + } catch (RuntimeException e) { + // so what? + } + } + } + + static class ReactiveClientHolder implements Store.CloseableResource { + + final com.mongodb.reactivestreams.client.MongoClient client; + + public ReactiveClientHolder(com.mongodb.reactivestreams.client.MongoClient client) { + this.client = client; + } + + @Override + public void close() { + + try { + client.close(); + } catch (RuntimeException e) { + // so what? + } + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java index f64569b679..28760fd86f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReplSetClient.java @@ -22,7 +22,14 @@ import java.lang.annotation.Target; /** + * Marks a field or method as to be autowired by JUnit's dependency injection facilities for injection of a MongoDB + * client instance connected to a replica set. Depends on {@link MongoClientExtension}. + * * @author Christoph Strobl + * @see com.mongodb.client.MongoClient + * @see com.mongodb.reactivestreams.client.MongoClient + * @see Client + * @see MongoClientExtension */ @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) diff --git a/spring-data-mongodb/src/test/resources/logback.xml b/spring-data-mongodb/src/test/resources/logback.xml index 5cfaf97c01..a36841c97c 100644 --- a/spring-data-mongodb/src/test/resources/logback.xml +++ b/spring-data-mongodb/src/test/resources/logback.xml @@ -12,7 +12,7 @@ --> - + From 3b6880edfd91d9012ffbcdf9573a91b13e8a2779 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 25 Nov 2019 11:06:53 +0100 Subject: [PATCH 0074/1381] DATAMONGO-2400 - Consider java.time.Instant a store supported native type and add configuration options for other java.time types. We now use the MongoDB Java driver InstantCodec instead of a dedicated converter. Other java.time types like LocalDate use a different zone offset when writing values which can lead to unexpected behavior. Therefore we added configuration options to MongoCustomConversions that allow to tell the conversion sub system which approach to use when writing those kind of types. Original pull request: #810. --- .../config/MongoConfigurationSupport.java | 28 ++- .../core/convert/MongoCustomConversions.java | 195 +++++++++++++++++- .../core/mapping/MongoSimpleTypes.java | 2 + .../convert/MappingMongoConverterTests.java | 66 +++++- .../MappingMongoConverterUnitTests.java | 21 ++ src/main/asciidoc/reference/mapping.adoc | 33 ++- 6 files changed, 327 insertions(+), 18 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index a616467838..b3c771bc44 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -32,6 +32,7 @@ import org.springframework.data.mapping.model.FieldNamingStrategy; import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.util.ClassUtils; @@ -92,14 +93,35 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException { /** * Register custom {@link Converter}s in a {@link CustomConversions} object if required. These - * {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and - * {@link #mongoMappingContext()}. Returns an empty {@link MongoCustomConversions} instance by default. + * {@link CustomConversions} will be registered with the + * {@link org.springframework.data.mongodb.core.convert.MappingMongoConverter} and {@link #mongoMappingContext()}. + * Returns an empty {@link MongoCustomConversions} instance by default.
      + * NOTE: Use {@link #customConversionsConfiguration(MongoConverterConfigurationAdapter)} to configure + * MongoDB native simple types and register custom {@link Converter converters}. * * @return must not be {@literal null}. */ @Bean public CustomConversions customConversions() { - return new MongoCustomConversions(Collections.emptyList()); + return new MongoCustomConversions(this::customConversionsConfiguration); + } + + /** + * Configuration hook for {@link MongoCustomConversions} creation. + * + * @param converterConfigurationAdapter never {@literal null}. + * @since 2.3 + */ + protected void customConversionsConfiguration(MongoConverterConfigurationAdapter converterConfigurationAdapter) { + + /* + * In case you want to use the MongoDB Java Driver native Codecs for java.time types instead of the converters SpringData + * ships with, then you may want to call the following here. + * + * converterConfigurationAdapter.useNativeDriverJavaTimeCodecs() + * + * But please, be careful! LocalDate, LocalTime and LocalDateTime will be stored with different values by doing so. + */ } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java index 7e56590459..ff9023a4f3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java @@ -15,26 +15,42 @@ */ package org.springframework.data.mongodb.core.convert; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.ConverterFactory; import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; import org.springframework.data.convert.JodaTimeConverters; import org.springframework.data.convert.WritingConverter; +import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Value object to capture custom conversion. {@link MongoCustomConversions} also act as factory for * {@link org.springframework.data.mapping.model.SimpleTypeHolder} * * @author Mark Paluch + * @author Christoph Strobl * @since 2.0 * @see org.springframework.data.convert.CustomConversions * @see org.springframework.data.mapping.model.SimpleTypeHolder @@ -71,7 +87,30 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus * @param converters must not be {@literal null}. */ public MongoCustomConversions(List converters) { - super(STORE_CONVERSIONS, converters); + + this(converterConfigurationAdapter -> { + + converterConfigurationAdapter.useSpringDataJavaTimeCodecs(); + converterConfigurationAdapter.registerConverters(converters); + }); + } + + /** + * Functional style {@link org.springframework.data.convert.CustomConversions} creation giving users a convenient way + * of configuring store specific capabilities by providing deferred hooks to what will be configured when creating the + * {@link org.springframework.data.convert.CustomConversions#CustomConversions(ConverterConfiguration) instance}. + * + * @param conversionConfiguration must not be {@literal null}. + * @since 2.3 + */ + public MongoCustomConversions(Consumer conversionConfiguration) { + + super(() -> { + + MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter(); + conversionConfiguration.accept(adapter); + return adapter.createConverterConfiguration(); + }); } @WritingConverter @@ -99,4 +138,158 @@ public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDe return source != null ? source.toString() : null; } } + + /** + * {@link MongoConverterConfigurationAdapter} encapsulates creation of + * {@link org.springframework.data.convert.CustomConversions.ConverterConfiguration} with MongoDB specifics. + * + * @author Christoph Strobl + * @since 2.3 + */ + public static class MongoConverterConfigurationAdapter { + + /** + * List of {@literal java.time} types having different representation when rendered via the native + * {@link org.bson.codecs.Codec} than the Spring Data {@link Converter}. + */ + private static final List> JAVA_DRIVER_TIME_SIMPLE_TYPES = Arrays.asList(LocalDate.class, LocalTime.class, + LocalDateTime.class); + + private boolean useNativeDriverJavaTimeCodecs = false; + private List customConverters = new ArrayList<>(); + + /** + * Set wether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for + * {@link org.bson.codecs.jsr310.LocalDateCodec LocalDate}, {@link org.bson.codecs.jsr310.LocalTimeCodec LocalTime} + * and {@link org.bson.codecs.jsr310.LocalDateTimeCodec LocalDateTime} using a {@link ZoneOffset#UTC}. + * + * @param useNativeDriverJavaTimeCodecs + * @return this. + */ + public MongoConverterConfigurationAdapter useNativeDriverJavaTimeCodecs(boolean useNativeDriverJavaTimeCodecs) { + + this.useNativeDriverJavaTimeCodecs = useNativeDriverJavaTimeCodecs; + return this; + } + + /** + * Use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for + * {@link org.bson.codecs.jsr310.LocalDateCodec LocalDate}, {@link org.bson.codecs.jsr310.LocalTimeCodec LocalTime} + * and {@link org.bson.codecs.jsr310.LocalDateTimeCodec LocalDateTime} using a {@link ZoneOffset#UTC}. + * + * @return this. + * @see #useNativeDriverJavaTimeCodecs(boolean) + */ + public MongoConverterConfigurationAdapter useNativeDriverJavaTimeCodecs() { + return useNativeDriverJavaTimeCodecs(true); + } + + /** + * Use SpringData {@link Converter Jsr310 converters} for + * {@link org.springframework.data.convert.Jsr310Converters.LocalDateToDateConverter LocalDate}, + * {@link org.springframework.data.convert.Jsr310Converters.LocalTimeToDateConverter LocalTime} and + * {@link org.springframework.data.convert.Jsr310Converters.LocalDateTimeToDateConverter LocalDateTime} using the + * {@link ZoneId#systemDefault()}. + * + * @return this. + * @see #useNativeDriverJavaTimeCodecs(boolean) + */ + public MongoConverterConfigurationAdapter useSpringDataJavaTimeCodecs() { + return useNativeDriverJavaTimeCodecs(false); + } + + /** + * Add a custom {@link Converter} implementation. + * + * @param converter must not be {@literal null}. + * @return this. + */ + public MongoConverterConfigurationAdapter registerConverter(Converter converter) { + + Assert.notNull(converter, "Converter must not be null!"); + customConverters.add(converter); + return this; + } + + /** + * Add a custom {@link ConverterFactory} implementation. + * + * @param converterFactory must not be {@literal null}. + * @return this. + */ + public MongoConverterConfigurationAdapter registerConverterFactory(ConverterFactory converterFactory) { + + Assert.notNull(converterFactory, "ConverterFactory must not be null!"); + customConverters.add(converterFactory); + return this; + } + + /** + * Add {@link Converter converters}, {@link ConverterFactory factories}, ... + * + * @param converters must not be {@literal null} nor contain {@literal null} values. + * @return this. + */ + public MongoConverterConfigurationAdapter registerConverters(Collection converters) { + + Assert.noNullElements(converters, "Converters must not be null nor contain null values!"); + customConverters.addAll(converters); + return this; + } + + ConverterConfiguration createConverterConfiguration() { + + if (!useNativeDriverJavaTimeCodecs) { + return new ConverterConfiguration(STORE_CONVERSIONS, this.customConverters); + } + + /* + * We need to have those converters using UTC as the default ones would go on with the systemDefault. + */ + List converters = new ArrayList<>(); + converters.add(DateToUtcLocalDateConverter.INSTANCE); + converters.add(DateToUtcLocalTimeConverter.INSTANCE); + converters.add(DateToUtcLocalDateTimeConverter.INSTANCE); + converters.addAll(STORE_CONVERTERS); + + /* + * Right, good catch! We also need to make sure to remove default writing converters for java.time types. + */ + List skipConverterRegistrationFor = JAVA_DRIVER_TIME_SIMPLE_TYPES.stream() // + .map(it -> new ConvertiblePair(it, Date.class)) // + .collect(Collectors.toList()); // + + StoreConversions storeConversions = StoreConversions + .of(new SimpleTypeHolder(new HashSet<>(JAVA_DRIVER_TIME_SIMPLE_TYPES), MongoSimpleTypes.HOLDER), converters); + + return new ConverterConfiguration(storeConversions, this.customConverters, skipConverterRegistrationFor); + } + + private enum DateToUtcLocalDateTimeConverter implements Converter { + INSTANCE; + + @Override + public LocalDateTime convert(Date source) { + return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC")); + } + } + + private enum DateToUtcLocalTimeConverter implements Converter { + INSTANCE; + + @Override + public LocalTime convert(Date source) { + return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime(); + } + } + + private enum DateToUtcLocalDateConverter implements Converter { + INSTANCE; + + @Override + public LocalDate convert(Date source) { + return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate(); + } + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java index 27a4ac9e5c..21cee062ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.core.mapping; import java.math.BigInteger; +import java.time.Instant; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -71,6 +72,7 @@ public abstract class MongoSimpleTypes { simpleTypes.add(Pattern.class); simpleTypes.add(Symbol.class); simpleTypes.add(UUID.class); + simpleTypes.add(Instant.class); simpleTypes.add(BsonBinary.class); simpleTypes.add(BsonBoolean.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index f44a367f39..906bcf1a8c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -24,6 +24,11 @@ import lombok.Data; import lombok.NoArgsConstructor; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.Arrays; import java.util.List; @@ -40,6 +45,7 @@ import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; /** * Integration tests for {@link MappingMongoConverter}. @@ -49,6 +55,7 @@ @ExtendWith(MongoClientExtension.class) public class MappingMongoConverterTests { + public static final String DATABASE = "mapping-converter-tests"; static @Client MongoClient client; MappingMongoConverter converter; @@ -58,21 +65,22 @@ public class MappingMongoConverterTests { @BeforeEach public void setUp() { - client.getDatabase("mapping-converter-tests").drop(); + client.getDatabase(DATABASE).drop(); - MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, "mapping-converter-tests"); + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); dbRefResolver = spy(new DefaultDbRefResolver(factory)); mappingContext = new MongoMappingContext(); mappingContext.afterPropertiesSet(); converter = new MappingMongoConverter(dbRefResolver, mappingContext); + converter.afterPropertiesSet(); } @Test // DATAMONGO-2004 public void resolvesLazyDBRefOnAccess() { - client.getDatabase("mapping-converter-tests").getCollection("samples") + client.getDatabase(DATABASE).getCollection("samples") .insertMany(Arrays.asList(new Document("_id", "sample-1").append("value", "one"), new Document("_id", "sample-2").append("value", "two"))); @@ -93,7 +101,7 @@ public void resolvesLazyDBRefOnAccess() { @Test // DATAMONGO-2004 public void resolvesLazyDBRefConstructorArgOnAccess() { - client.getDatabase("mapping-converter-tests").getCollection("samples") + client.getDatabase(DATABASE).getCollection("samples") .insertMany(Arrays.asList(new Document("_id", "sample-1").append("value", "one"), new Document("_id", "sample-2").append("value", "two"))); @@ -111,6 +119,31 @@ public void resolvesLazyDBRefConstructorArgOnAccess() { verify(dbRefResolver).bulkFetch(any()); } + @Test // DATAMONGO-2400 + public void readJavaTimeValuesWrittenViaCodec() { + + configureConverterWithNativeJavaTimeCodec(); + MongoCollection mongoCollection = client.getDatabase(DATABASE).getCollection("java-time-types"); + + Instant now = Instant.now(); + WithJavaTimeTypes source = WithJavaTimeTypes.withJavaTimeTypes(now); + source.id = "id-1"; + + mongoCollection.insertOne(source.toDocument()); + + assertThat(converter.read(WithJavaTimeTypes.class, mongoCollection.find(new Document("_id", source.id)).first())) + .isEqualTo(source); + } + + void configureConverterWithNativeJavaTimeCodec() { + + converter = new MappingMongoConverter(dbRefResolver, mappingContext); + converter.setCustomConversions(new MongoCustomConversions(config -> { + config.useNativeDriverJavaTimeCodecs(); + })); + converter.afterPropertiesSet(); + } + public static class WithLazyDBRef { @Id String id; @@ -145,4 +178,29 @@ static class Sample { @Id String id; String value; } + + @Data + static class WithJavaTimeTypes { + + @Id String id; + LocalDate localDate; + LocalTime localTime; + LocalDateTime localDateTime; + + static WithJavaTimeTypes withJavaTimeTypes(Instant instant) { + + WithJavaTimeTypes instance = new WithJavaTimeTypes(); + + instance.localDate = LocalDate.from(instant.atZone(ZoneId.of("CET"))); + instance.localTime = LocalTime.from(instant.atZone(ZoneId.of("CET"))); + instance.localDateTime = LocalDateTime.from(instant.atZone(ZoneId.of("CET"))); + + return instance; + } + + Document toDocument() { + return new Document("_id", id).append("localDate", localDate).append("localTime", localTime) + .append("localDateTime", localDateTime); + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index e2a8e12c3d..c4ad84f8c2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -1072,6 +1072,27 @@ public void readsEmptyCollectionIntoConstructorCorrectly() { assertThat(result.attributes).isNotNull(); } + @Test // DATAMONGO-2400 + public void writeJavaTimeValuesViaCodec() { + + configureConverterWithNativeJavaTimeCodec(); + TypeWithLocalDateTime source = new TypeWithLocalDateTime(); + + org.bson.Document target = new org.bson.Document(); + converter.write(source, target); + + assertThat(target).containsEntry("date", source.date); + } + + void configureConverterWithNativeJavaTimeCodec() { + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(new MongoCustomConversions(config -> { + config.useNativeDriverJavaTimeCodecs(); + })); + converter.afterPropertiesSet(); + } + private static void assertSyntheticFieldValueOf(Object target, Object expected) { for (int i = 0; i < 10; i++) { diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index b034cdf674..968000e339 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -177,14 +177,24 @@ calling `get()` before the actual conversion | converter | `{"currencyCode" : "EUR"}` +| `Instant` + +(Java 8) +| native +| `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` + +| `Instant` + +(Joda, JSR310-BackPort) +| converter +| `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` + | `LocalDate` + (Joda, Java 8, JSR310-BackPort) -| converter +| converter / native (Java8)footnote:[Uses UTC zone offset. Configure via <>] | `{"date" : ISODate("2019-11-12T00:00:00.000Z")}` -| `LocalDateTime`, `LocalTime`, `Instant` + +| `LocalDateTime`, `LocalTime` + (Joda, Java 8, JSR310-BackPort) -| converter +| converter / native (Java8)footnote:[Uses UTC zone offset. Configure via <>] | `{"date" : ISODate("2019-11-12T23:00:00.809Z")}` | `DateTime` (Joda) @@ -258,6 +268,8 @@ You can configure the `MappingMongoConverter` as well as `com.mongodb.client.Mon ==== [source,java] ---- +import com.mongodb.client.MongoClients; + @Configuration public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { @@ -271,6 +283,8 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { return "database"; } + // the following are optional + @Override public String getMappingBasePackage() { return "com.bigbank.domain"; @@ -278,13 +292,11 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { // the following are optional - @Bean @Override - public CustomConversions customConversions() throws Exception { - List> converterList = new ArrayList>(); - converterList.add(new org.springframework.data.mongodb.test.PersonReadConverter()); - converterList.add(new org.springframework.data.mongodb.test.PersonWriteConverter()); - return new CustomConversions(converterList); + void customConversionsConfiguration(MongoConverterConfigurationAdapter adapter) { + + adapter.registerConverter(new org.springframework.data.mongodb.test.PersonReadConverter()); + adapter.registerConverter(new org.springframework.data.mongodb.test.PersonWriteConverter()); } @Bean @@ -297,7 +309,8 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { `AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. -You can add additional converters to the converter by overriding the `customConversions` method. Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure. +You can add additional converters to the converter by overriding the `customConversionsConfiguration` method. +Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure. NOTE: `AbstractMongoClientConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`. From e9d14f41a54acd71125e39ec26916e4a42bbd74e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 7 Feb 2020 12:32:38 +0100 Subject: [PATCH 0075/1381] DATAMONGO-2400 - Polishing. Adapt to changes in commons. Add functional create method to MongoCustomConversions. Update Javadoc and reference documentation. Truncate precision for Java 11 build compatibility in tests. Original pull request: #810. --- .../config/MongoConfigurationSupport.java | 23 +++--- .../core/convert/MongoCustomConversions.java | 80 ++++++++++++------- .../convert/MappingMongoConverterTests.java | 9 ++- .../MappingMongoConverterUnitTests.java | 6 +- src/main/asciidoc/reference/mapping.adoc | 8 +- 5 files changed, 73 insertions(+), 53 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index b3c771bc44..445c4ef793 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -95,15 +95,16 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException { * Register custom {@link Converter}s in a {@link CustomConversions} object if required. These * {@link CustomConversions} will be registered with the * {@link org.springframework.data.mongodb.core.convert.MappingMongoConverter} and {@link #mongoMappingContext()}. - * Returns an empty {@link MongoCustomConversions} instance by default.
      - * NOTE: Use {@link #customConversionsConfiguration(MongoConverterConfigurationAdapter)} to configure - * MongoDB native simple types and register custom {@link Converter converters}. + * Returns an empty {@link MongoCustomConversions} instance by default. + *

      + * NOTE: Use {@link #configureConverters(MongoConverterConfigurationAdapter)} to configure MongoDB + * native simple types and register custom {@link Converter converters}. * * @return must not be {@literal null}. */ @Bean public CustomConversions customConversions() { - return new MongoCustomConversions(this::customConversionsConfiguration); + return MongoCustomConversions.create(this::configureConverters); } /** @@ -111,17 +112,11 @@ public CustomConversions customConversions() { * * @param converterConfigurationAdapter never {@literal null}. * @since 2.3 + * @see MongoConverterConfigurationAdapter#useNativeDriverJavaTimeCodecs() + * @see MongoConverterConfigurationAdapter#useSpringDataJavaTimeCodecs() */ - protected void customConversionsConfiguration(MongoConverterConfigurationAdapter converterConfigurationAdapter) { - - /* - * In case you want to use the MongoDB Java Driver native Codecs for java.time types instead of the converters SpringData - * ships with, then you may want to call the following here. - * - * converterConfigurationAdapter.useNativeDriverJavaTimeCodecs() - * - * But please, be careful! LocalDate, LocalTime and LocalDateTime will be stored with different values by doing so. - */ + protected void configureConverters(MongoConverterConfigurationAdapter converterConfigurationAdapter) { + } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java index ff9023a4f3..aa96f9cab6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java @@ -31,13 +31,11 @@ import java.util.Locale; import java.util.Set; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterFactory; import org.springframework.core.convert.converter.GenericConverter; -import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; import org.springframework.data.convert.JodaTimeConverters; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mapping.model.SimpleTypeHolder; @@ -87,12 +85,17 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus * @param converters must not be {@literal null}. */ public MongoCustomConversions(List converters) { + this(MongoConverterConfigurationAdapter.from(converters)); + } - this(converterConfigurationAdapter -> { - - converterConfigurationAdapter.useSpringDataJavaTimeCodecs(); - converterConfigurationAdapter.registerConverters(converters); - }); + /** + * Create a new {@link MongoCustomConversions} given {@link MongoConverterConfigurationAdapter}. + * + * @param conversionConfiguration must not be {@literal null}. + * @since 2.3 + */ + protected MongoCustomConversions(MongoConverterConfigurationAdapter conversionConfiguration) { + super(conversionConfiguration.createConverterConfiguration()); } /** @@ -100,17 +103,15 @@ public MongoCustomConversions(List converters) { * of configuring store specific capabilities by providing deferred hooks to what will be configured when creating the * {@link org.springframework.data.convert.CustomConversions#CustomConversions(ConverterConfiguration) instance}. * - * @param conversionConfiguration must not be {@literal null}. + * @param configurer must not be {@literal null}. * @since 2.3 */ - public MongoCustomConversions(Consumer conversionConfiguration) { + public static MongoCustomConversions create(Consumer configurer) { - super(() -> { + MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter(); + configurer.accept(adapter); - MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter(); - conversionConfiguration.accept(adapter); - return adapter.createConverterConfiguration(); - }); + return new MongoCustomConversions(adapter); } @WritingConverter @@ -152,14 +153,32 @@ public static class MongoConverterConfigurationAdapter { * List of {@literal java.time} types having different representation when rendered via the native * {@link org.bson.codecs.Codec} than the Spring Data {@link Converter}. */ - private static final List> JAVA_DRIVER_TIME_SIMPLE_TYPES = Arrays.asList(LocalDate.class, LocalTime.class, - LocalDateTime.class); + private static final Set> JAVA_DRIVER_TIME_SIMPLE_TYPES = new HashSet<>( + Arrays.asList(LocalDate.class, LocalTime.class, LocalDateTime.class)); private boolean useNativeDriverJavaTimeCodecs = false; - private List customConverters = new ArrayList<>(); + private final List customConverters = new ArrayList<>(); /** - * Set wether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for + * Create a {@link MongoConverterConfigurationAdapter} using the provided {@code converters} and our own codecs for + * JSR-310 types. + * + * @param converters must not be {@literal null}. + * @return + */ + public static MongoConverterConfigurationAdapter from(List converters) { + + Assert.notNull(converters, "Converters must not be null"); + + MongoConverterConfigurationAdapter converterConfigurationAdapter = new MongoConverterConfigurationAdapter(); + converterConfigurationAdapter.useSpringDataJavaTimeCodecs(); + converterConfigurationAdapter.registerConverters(converters); + + return converterConfigurationAdapter; + } + + /** + * Set whether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for * {@link org.bson.codecs.jsr310.LocalDateCodec LocalDate}, {@link org.bson.codecs.jsr310.LocalTimeCodec LocalTime} * and {@link org.bson.codecs.jsr310.LocalDateTimeCodec LocalDateTime} using a {@link ZoneOffset#UTC}. * @@ -232,7 +251,9 @@ public MongoConverterConfigurationAdapter registerConverterFactory(ConverterFact */ public MongoConverterConfigurationAdapter registerConverters(Collection converters) { + Assert.notNull(converters, "Converters must not be null"); Assert.noNullElements(converters, "Converters must not be null nor contain null values!"); + customConverters.addAll(converters); return this; } @@ -246,23 +267,26 @@ ConverterConfiguration createConverterConfiguration() { /* * We need to have those converters using UTC as the default ones would go on with the systemDefault. */ - List converters = new ArrayList<>(); + List converters = new ArrayList<>(STORE_CONVERTERS.size() + 3); converters.add(DateToUtcLocalDateConverter.INSTANCE); converters.add(DateToUtcLocalTimeConverter.INSTANCE); converters.add(DateToUtcLocalDateTimeConverter.INSTANCE); converters.addAll(STORE_CONVERTERS); - /* - * Right, good catch! We also need to make sure to remove default writing converters for java.time types. - */ - List skipConverterRegistrationFor = JAVA_DRIVER_TIME_SIMPLE_TYPES.stream() // - .map(it -> new ConvertiblePair(it, Date.class)) // - .collect(Collectors.toList()); // - StoreConversions storeConversions = StoreConversions - .of(new SimpleTypeHolder(new HashSet<>(JAVA_DRIVER_TIME_SIMPLE_TYPES), MongoSimpleTypes.HOLDER), converters); + .of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), converters); + + return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> { + + // Avoid default registrations + + if (JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType()) + && Date.class.isAssignableFrom(convertiblePair.getTargetType())) { + return false; + } - return new ConverterConfiguration(storeConversions, this.customConverters, skipConverterRegistrationFor); + return true; + }); } private enum DateToUtcLocalDateTimeConverter implements Converter { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index 906bcf1a8c..dcad856382 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -29,6 +29,7 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; +import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.List; @@ -39,6 +40,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.test.util.Client; @@ -125,7 +127,7 @@ public void readJavaTimeValuesWrittenViaCodec() { configureConverterWithNativeJavaTimeCodec(); MongoCollection mongoCollection = client.getDatabase(DATABASE).getCollection("java-time-types"); - Instant now = Instant.now(); + Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS); WithJavaTimeTypes source = WithJavaTimeTypes.withJavaTimeTypes(now); source.id = "id-1"; @@ -138,9 +140,8 @@ public void readJavaTimeValuesWrittenViaCodec() { void configureConverterWithNativeJavaTimeCodec() { converter = new MappingMongoConverter(dbRefResolver, mappingContext); - converter.setCustomConversions(new MongoCustomConversions(config -> { - config.useNativeDriverJavaTimeCodecs(); - })); + converter.setCustomConversions( + MongoCustomConversions.create(MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs)); converter.afterPropertiesSet(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index c4ad84f8c2..c46f599f38 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -1087,9 +1087,9 @@ public void writeJavaTimeValuesViaCodec() { void configureConverterWithNativeJavaTimeCodec() { converter = new MappingMongoConverter(resolver, mappingContext); - converter.setCustomConversions(new MongoCustomConversions(config -> { - config.useNativeDriverJavaTimeCodecs(); - })); + + converter.setCustomConversions(MongoCustomConversions + .create(MongoCustomConversions.MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs)); converter.afterPropertiesSet(); } diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 968000e339..35d7b83876 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -1,3 +1,4 @@ + [[mapping-chapter]] = Mapping @@ -290,10 +291,8 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { return "com.bigbank.domain"; } - // the following are optional - @Override - void customConversionsConfiguration(MongoConverterConfigurationAdapter adapter) { + void configureConverters(MongoConverterConfigurationAdapter adapter) { adapter.registerConverter(new org.springframework.data.mongodb.test.PersonReadConverter()); adapter.registerConverter(new org.springframework.data.mongodb.test.PersonWriteConverter()); @@ -310,11 +309,12 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { `AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. You can add additional converters to the converter by overriding the `customConversionsConfiguration` method. +MongoDB's native JSR-310 support can be enabled through `MongoConverterConfigurationAdapter.useNativeDriverJavaTimeCodecs()`. Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure. NOTE: `AbstractMongoClientConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`. -Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows: +Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows: .XML schema to configure MongoDB mapping support ==== From ca802c7ca419d0ad31349b90f062ffba01cd864f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 11 Feb 2020 10:57:52 +0100 Subject: [PATCH 0076/1381] DATAMONGO-2470 - Adapt tests to AssertJ 3.15.0. --- .../data/mongodb/core/GeoCommandStatisticsUnitTests.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java index a9424c1321..34e511d916 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java @@ -24,6 +24,7 @@ * Unit tests for {@link GeoCommandStatistics}. * * @author Oliver Gierke + * @author Mark Paluch * @soundtrack Fruitcake - Jeff Coffin (The Inside of the Outside) */ public class GeoCommandStatisticsUnitTests { @@ -37,10 +38,10 @@ public void rejectsNullCommandResult() { public void fallsBackToNanIfNoAverageDistanceIsAvailable() { GeoCommandStatistics statistics = GeoCommandStatistics.from(new Document("stats", null)); - assertThat(statistics.getAverageDistance()).isEqualTo(Double.NaN); + assertThat(statistics.getAverageDistance()).isNaN(); statistics = GeoCommandStatistics.from(new Document("stats", new Document())); - assertThat(statistics.getAverageDistance()).isEqualTo(Double.NaN); + assertThat(statistics.getAverageDistance()).isNaN(); } @Test // DATAMONGO-1361 From 0f4f745d3c888233ff0961ce661c229bf30a5666 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Feb 2020 14:46:51 +0100 Subject: [PATCH 0077/1381] DATAMONGO-2456 - Updated changelog. --- src/main/resources/changelog.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 4e89bac199..3eef84baef 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,27 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.M3 (2020-02-12) +---------------------------------------- +* DATAMONGO-2470 - Adapt tests to AssertJ 3.15.0. +* DATAMONGO-2464 - Fix code examples in reference documentation. +* DATAMONGO-2462 - Move off deprecated EntityInstantiators. +* DATAMONGO-2461 - Fix Jenkins build. +* DATAMONGO-2460 - @Field annotation behaviour changed. +* DATAMONGO-2459 - Update Documentation of Reactive Repositories to mention usage of PageRequest. +* DATAMONGO-2457 - Reference documentation: Text does not match with code example. +* DATAMONGO-2456 - Release 3.0 M3 (Neumann). +* DATAMONGO-2449 - Add aggregation options parameters to @Aggregation annotation. +* DATAMONGO-2427 - Switch to 4.0-beta1 MongoDB driver. +* DATAMONGO-2417 - Typesafe Extension Function for ReactiveFindOperation.FindDistinct. +* DATAMONGO-2406 - Allow Mono as return type for derived deleteBy queries. +* DATAMONGO-2400 - Read/write converters not working. +* DATAMONGO-2365 - Parameter hint in Query#hint is not index name. +* DATAMONGO-2249 - Query hint leads to error when executed via reactive template. +* DATAMONGO-2079 - MappingMongoConverter cannot be proxied because it implements the package-private ValueResolver interface. +* DATAMONGO-1997 - Add support to return the single deleted item for a deleteBy query method. + + Changes in version 3.0.0.M2 (2020-01-17) ---------------------------------------- * DATAMONGO-2454 - Release 3.0 M2 (Neumann). @@ -2889,3 +2910,4 @@ Repository + From 534ce2e5f5d1b2e4f2538612d1d5f3bc127ee8df Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Feb 2020 14:46:56 +0100 Subject: [PATCH 0078/1381] DATAMONGO-2456 - Prepare 3.0 M3 (Neumann). --- pom.xml | 16 ++++++++++------ src/main/resources/notice.txt | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 9db0441fd9..2dfc256cf5 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M3 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M3 4.0.0-beta1 ${mongo} 1.19 @@ -134,14 +134,18 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot https://oss.sonatype.org/content/repositories/snapshots - false - true + + false + + + true + diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 81dd640c79..9097e23c55 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 M2 +Spring Data MongoDB 3.0 M3 Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -10,3 +10,4 @@ code for the these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. + From 087f8f78b59325ce1a23908545acc8c93a1430ad Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Feb 2020 14:47:16 +0100 Subject: [PATCH 0079/1381] DATAMONGO-2456 - Release version 3.0 M3 (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2dfc256cf5..2ccb2c5163 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M3 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..e91207e5bc 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M3 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..3772ab93f0 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M3 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 76df2c09ee..b398281511 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M3 ../pom.xml From a7c25c8524f445bddba0854bf2c37483b5b0e595 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Feb 2020 15:04:21 +0100 Subject: [PATCH 0080/1381] DATAMONGO-2456 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2ccb2c5163..2dfc256cf5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M3 + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index e91207e5bc..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M3 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 3772ab93f0..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M3 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index b398281511..76df2c09ee 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M3 + 3.0.0.BUILD-SNAPSHOT ../pom.xml From 65508eb01b8634644f7b1de2afa5f50d64526fd5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Feb 2020 15:04:22 +0100 Subject: [PATCH 0081/1381] DATAMONGO-2456 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2dfc256cf5..5401e36809 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.M3 + 2.3.0.BUILD-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.M3 + 2.3.0.BUILD-SNAPSHOT 4.0.0-beta1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From f153399c3b383f142e9de67abaad4fd46dedd175 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 14 Feb 2020 07:44:03 +0100 Subject: [PATCH 0082/1381] DATAMONGO-2474 - Upgrade to MongoDB driver 4.0.0-rc0. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5401e36809..8059c54cff 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 4.0.0-beta1 + 4.0.0-rc0 ${mongo} 1.19 From 6259cd2c3b00f0f58693b20652f556d5afa83b8f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 6 Feb 2020 08:16:59 +0100 Subject: [PATCH 0083/1381] DATAMONGO-2341 - Support shard key derivation in save operations via @Sharded annotation. Spring Data MongoDB uses the @Sharded annotation to identify entities stored in sharded collections. The shard key consists of a single or multiple properties present in every document within the target collection, and is used to distribute them across shards. Spring Data MongoDB will do best effort optimisations for sharded scenarios when using repositories by adding required shard key information, if not already present, to replaceOne filter queries when upserting entities. This may require an additional server round trip to determine the actual value of the current shard key. By setting @Sharded(immutableKey = true) no attempt will be made to check if an entities shard key changed. Please see the MongoDB Documentation for further details and the list below for which operations are eligible to auto include the shard key. * Reactive/CrudRepository.save(...) * Reactive/CrudRepository.saveAll(...) * Reactive/MongoTemplate.save(...) Original pull request: #833. --- .../data/mongodb/core/MappedDocument.java | 6 +- .../data/mongodb/core/MongoTemplate.java | 48 ++++-- .../data/mongodb/core/QueryOperations.java | 76 ++++++++- .../mongodb/core/ReactiveMongoTemplate.java | 44 ++++- .../mapping/BasicMongoPersistentEntity.java | 30 ++++ .../core/mapping/MongoPersistentEntity.java | 34 ++++ .../data/mongodb/core/mapping/ShardKey.java | 138 ++++++++++++++++ .../data/mongodb/core/mapping/Sharded.java | 92 +++++++++++ .../core/mapping/ShardingStrategy.java | 35 ++++ .../data/mongodb/util/BsonUtils.java | 4 +- .../mongodb/core/MongoTemplateUnitTests.java | 89 +++++++++++ .../core/ReactiveMongoTemplateUnitTests.java | 96 +++++++++++ .../ShardedEntityWithDefaultShardKey.java | 40 +++++ ...EntityWithNonDefaultImmutableShardKey.java | 40 +++++ .../ShardedEntityWithNonDefaultShardKey.java | 40 +++++ ...VersionedEntityWithNonDefaultShardKey.java | 43 +++++ .../core/UpdateOperationsUnitTests.java | 150 ++++++++++++++++++ .../BasicMongoPersistentEntityUnitTests.java | 41 +++++ src/main/asciidoc/index.adoc | 1 + src/main/asciidoc/reference/sharding.adoc | 70 ++++++++ 20 files changed, 1093 insertions(+), 24 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithDefaultShardKey.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultImmutableShardKey.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultShardKey.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedVersionedEntityWithNonDefaultShardKey.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java create mode 100644 src/main/asciidoc/reference/sharding.adoc diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java index 72b351fc41..7df9503caa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java @@ -80,7 +80,11 @@ public boolean isIdPresent(Class type) { } public Bson getIdFilter() { - return Filters.eq(ID_FIELD, document.get(ID_FIELD)); + return new Document(ID_FIELD, document.get(ID_FIELD)); + } + + public Object get(String key) { + return document.get(key); } public UpdateDefinition updateWithoutId() { 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 96b2d4620c..4179c0f67b 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 @@ -33,7 +33,6 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -1480,23 +1479,38 @@ protected Object saveDocument(String collectionName, Document dbDoc, Class en } return execute(collectionName, collection -> { + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass, dbDoc, null); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); MappedDocument mapped = MappedDocument.of(dbDoc); + MongoCollection collectionToUse = writeConcernToUse == null // + ? collection // + : collection.withWriteConcern(writeConcernToUse); + if (!mapped.hasId()) { - if (writeConcernToUse == null) { - collection.insertOne(dbDoc); - } else { - collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc); - } - } else if (writeConcernToUse == null) { - collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true)); + collectionToUse.insertOne(dbDoc); } else { - collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc, - new ReplaceOptions().upsert(true)); + + MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); + UpdateContext updateContext = queryOperations.replaceSingleContext(mapped, true); + Document replacement = updateContext.getMappedUpdate(entity); + + Document filter = updateContext.getMappedQuery(entity); + + if (updateContext.requiresShardKey(filter, entity)) { + + if (entity.getShardKey().isImmutable()) { + filter = updateContext.applyShardKey(entity, filter, null); + } else { + filter = updateContext.applyShardKey(entity, filter, + collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()); + } + } + + collectionToUse.replaceOne(filter, replacement, new ReplaceOptions().upsert(true)); } return mapped.getId(); }); @@ -1615,8 +1629,20 @@ protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefini if (!UpdateMapper.isUpdateObject(updateObj)) { + Document filter = new Document(queryObj); + + if (updateContext.requiresShardKey(filter, entity)) { + + if (entity.getShardKey().isImmutable()) { + filter = updateContext.applyShardKey(entity, filter, null); + } else { + filter = updateContext.applyShardKey(entity, filter, + collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()); + } + } + ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass); - return collection.replaceOne(queryObj, updateObj, replaceOptions); + return collection.replaceOne(filter, updateObj, replaceOptions); } else { return multi ? collection.updateMany(queryObj, updateObj, opts) : collection.updateOne(queryObj, updateObj, opts); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index 23c88f5600..f6852c3337 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -16,7 +16,10 @@ package org.springframework.data.mongodb.core; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -154,6 +157,15 @@ UpdateContext updateSingleContext(UpdateDefinition updateDefinition, Document qu return new UpdateContext(updateDefinition, query, false, upsert); } + /** + * @param replacement the {@link MappedDocument mapped replacement} document. + * @param upsert use {@literal true} to insert diff when no existing document found. + * @return new instance of {@link UpdateContext}. + */ + UpdateContext replaceSingleContext(MappedDocument replacement, boolean upsert) { + return new UpdateContext(replacement, upsert); + } + /** * Create a new {@link DeleteContext} instance removing all matching documents. * @@ -253,7 +265,6 @@ Document getMappedFields(@Nullable MongoPersistentEntity entity) { */ Document getMappedSort(@Nullable MongoPersistentEntity entity) { return queryMapper.getMappedSort(query.getSortObject(), entity); - } /** @@ -353,7 +364,6 @@ Class getMostSpecificConversionTargetType(Class requestedTargetType, Class if (ClassUtils.isAssignable(requestedTargetType, propertyType)) { conversionTargetType = propertyType; } - } catch (PropertyReferenceException e) { // just don't care about it as we default to Object.class anyway. } @@ -491,7 +501,9 @@ class UpdateContext extends QueryContext { private final boolean multi; private final boolean upsert; - private final UpdateDefinition update; + private final @Nullable UpdateDefinition update; + private final @Nullable MappedDocument mappedDocument; + private final Map, Document> mappedShardKey = new ConcurrentHashMap<>(1); /** * Create a new {@link UpdateContext} instance. @@ -520,6 +532,16 @@ class UpdateContext extends QueryContext { this.multi = multi; this.upsert = upsert; this.update = update; + this.mappedDocument = null; + } + + UpdateContext(MappedDocument update, boolean upsert) { + + super(new BasicQuery(new Document(BsonUtils.asMap(update.getIdFilter())))); + this.multi = false; + this.upsert = upsert; + this.mappedDocument = update; + this.update = null; } /** @@ -544,7 +566,7 @@ UpdateOptions getUpdateOptions(@Nullable Class domainType, @Nullable Consumer UpdateOptions options = new UpdateOptions(); options.upsert(upsert); - if (update.hasArrayFilters()) { + if (update != null && update.hasArrayFilters()) { options .arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList())); } @@ -602,6 +624,45 @@ Document getMappedQuery(@Nullable MongoPersistentEntity domainType) { return mappedQuery; } + Document applyShardKey(@Nullable MongoPersistentEntity domainType, Document filter, + @Nullable Document existing) { + + Document shardKeySource = existing != null ? existing + : mappedDocument != null ? mappedDocument.getDocument() : getMappedUpdate(domainType); + + Document filterWithShardKey = new Document(filter); + for (String key : getMappedShardKeyFields(domainType)) { + if (!filterWithShardKey.containsKey(key)) { + filterWithShardKey.append(key, shardKeySource.get(key)); + } + } + + return filterWithShardKey; + } + + boolean requiresShardKey(Document filter, @Nullable MongoPersistentEntity domainType) { + + if (multi || domainType == null || !domainType.isSharded() || domainType.idPropertyIsShardKey()) { + return false; + } + + if (filter.keySet().containsAll(getMappedShardKeyFields(domainType))) { + return false; + } + + return true; + } + + Set getMappedShardKeyFields(@Nullable MongoPersistentEntity entity) { + return getMappedShardKey(entity).keySet(); + } + + Document getMappedShardKey(@Nullable MongoPersistentEntity entity) { + + return mappedShardKey.computeIfAbsent(entity.getType(), + key -> queryMapper.getMappedFields(entity.getShardKey().getDocument(), entity)); + } + /** * Get the already mapped aggregation pipeline to use with an {@link #isAggregationUpdate()}. * @@ -625,8 +686,11 @@ List getUpdatePipeline(@Nullable Class domainType) { */ Document getMappedUpdate(@Nullable MongoPersistentEntity entity) { - return update instanceof MappedUpdate ? update.getUpdateObject() - : updateMapper.getMappedObject(update.getUpdateObject(), entity); + if (update != null) { + return update instanceof MappedUpdate ? update.getUpdateObject() + : updateMapper.getMappedObject(update.getUpdateObject(), entity); + } + return mappedDocument.getDocument(); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 63413b77bc..b2324f94f0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -39,7 +39,6 @@ import org.reactivestreams.Subscriber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -1638,9 +1637,31 @@ protected Mono saveDocument(String collectionName, Document document, Cl ? collection // : collection.withWriteConcern(writeConcernToUse); - Publisher publisher = !mapped.hasId() // - ? collectionToUse.insertOne(document) // - : collectionToUse.replaceOne(mapped.getIdFilter(), document, new ReplaceOptions().upsert(true)); + Publisher publisher = null; + if (!mapped.hasId()) { + publisher = collectionToUse.insertOne(document); + } else { + + MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); + UpdateContext updateContext = queryOperations.replaceSingleContext(mapped, true); + Document filter = updateContext.getMappedQuery(entity); + Document replacement = updateContext.getMappedUpdate(entity); + + Mono theFilter = Mono.just(filter); + + if(updateContext.requiresShardKey(filter, entity)) { + if (entity.getShardKey().isImmutable()) { + theFilter = Mono.just(updateContext.applyShardKey(entity, filter, null)); + } else { + theFilter = Mono.from( + collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()) + .defaultIfEmpty(replacement).map(it -> updateContext.applyShardKey(entity, filter, it)); + } + } + + publisher = theFilter.flatMap( + it -> Mono.from(collectionToUse.replaceOne(it, replacement, updateContext.getReplaceOptions(entityClass)))); + } return Mono.from(publisher).map(o -> mapped.getId()); }); @@ -1778,8 +1799,21 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla if (!UpdateMapper.isUpdateObject(updateObj)) { + Document filter = new Document(queryObj); + Mono theFilter = Mono.just(filter); + + if(updateContext.requiresShardKey(filter, entity)) { + if (entity.getShardKey().isImmutable()) { + theFilter = Mono.just(updateContext.applyShardKey(entity, filter, null)); + } else { + theFilter = Mono.from( + collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()) + .defaultIfEmpty(updateObj).map(it -> updateContext.applyShardKey(entity, filter, it)); + } + } + ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass); - return collectionToUse.replaceOne(queryObj, updateObj, replaceOptions); + return theFilter.flatMap(it -> Mono.from(collectionToUse.replaceOne(it, updateObj, replaceOptions))); } return multi ? collectionToUse.updateMany(queryObj, updateObj, updateOptions) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index f24ad0d78f..cbc67b13ab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -37,6 +37,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -63,6 +64,8 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity typeInformation) { this.collation = null; this.collationExpression = null; } + + this.shardKey = detectShardKey(this); } /* @@ -160,6 +165,11 @@ public org.springframework.data.mongodb.core.query.Collation getCollation() { : null; } + @Override + public ShardKey getShardKey() { + return shardKey; + } + /* * (non-Javadoc) * @see org.springframework.data.mapping.model.BasicPersistentEntity#verify() @@ -297,6 +307,26 @@ private static Expression detectExpression(@Nullable String potentialExpression) return expression instanceof LiteralExpression ? null : expression; } + @Nullable + private static ShardKey detectShardKey(BasicMongoPersistentEntity entity) { + + if (!entity.isAnnotationPresent(Sharded.class)) { + return ShardKey.none(); + } + + Sharded sharded = entity.getRequiredAnnotation(Sharded.class); + + String[] keyProperties = sharded.shardKey(); + if (ObjectUtils.isEmpty(keyProperties)) { + keyProperties = new String[] { "_id" }; + } + + ShardKey shardKey = ShardingStrategy.HASH.equals(sharded.shardingStrategy()) ? ShardKey.hash(keyProperties) + : ShardKey.range(keyProperties); + + return sharded.immutableKey() ? ShardKey.immutable(shardKey) : shardKey; + } + /** * Handler to collect {@link MongoPersistentProperty} instances and check that each of them is mapped to a distinct * field name. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java index 8d6aaa1504..1cef658d98 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java @@ -77,4 +77,38 @@ default boolean hasCollation() { return getCollation() != null; } + /** + * Get the entities shard key if defined. + * + * @return {@link ShardKey#none()} if not not set. + * @since 3.0 + */ + ShardKey getShardKey(); + + /** + * @return {@literal true} if the {@link #getShardKey() shard key} does not match {@link ShardKey#none()}. + * @since 3.0 + */ + default boolean isSharded() { + return !ShardKey.none().equals(getShardKey()); + } + + /** + * @return {@literal true} if the {@link #getShardKey() shard key} is the entities {@literal id} property. + * @since 3.0 + */ + default boolean idPropertyIsShardKey() { + + ShardKey shardKey = getShardKey(); + if (shardKey.size() != 1) { + return false; + } + String key = shardKey.getPropertyNames().iterator().next(); + if ("_id".equals(key)) { + return true; + } + + MongoPersistentProperty idProperty = getIdProperty(); + return idProperty != null && idProperty.getName().equals(key); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java new file mode 100644 index 0000000000..67ebf193da --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java @@ -0,0 +1,138 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.bson.Document; +import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; + +/** + * Value object representing an entities Shard + * Key used to distribute documents across a sharded MongoDB cluster. + *

      + * {@link ShardKey#isImmutable() Immutable} shard keys indicate a fixed value that is not updated (see + * MongoDB + * Reference: Change a Document’s Shard Key Value), which allows to skip server round trips in cases where a + * potential shard key change might have occurred. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ShardKey { + + private static final ShardKey NONE = new ShardKey(Collections.emptyList(), null, true); + + private final List propertyNames; + private final @Nullable ShardingStrategy shardingStrategy; + private final boolean immutable; + + private ShardKey(List propertyNames, @Nullable ShardingStrategy shardingStrategy, boolean immutable) { + + this.propertyNames = propertyNames; + this.shardingStrategy = shardingStrategy; + this.immutable = immutable; + } + + /** + * @return the number of properties used to form the shard key. + */ + public int size() { + return propertyNames.size(); + } + + /** + * @return the unmodifiable collection of property names forming the shard key. + */ + public Collection getPropertyNames() { + return propertyNames; + } + + /** + * @return {@literal true} if the shard key of an document does not change. + * @see MongoDB + * Reference: Change a Document’s Shard Key Value + */ + public boolean isImmutable() { + return immutable; + } + + /** + * Get the unmapped MongoDB representation of the {@link ShardKey}. + * + * @return never {@literal null}. + */ + public Document getDocument() { + + Document doc = new Document(); + for (String field : propertyNames) { + doc.append(field, shardingValue()); + } + return doc; + } + + private Object shardingValue() { + return ObjectUtils.nullSafeEquals(ShardingStrategy.HASH, shardingStrategy) ? "hash" : 1; + } + + /** + * {@link ShardKey} indicating no shard key has been defined. + * + * @return {@link #NONE} + */ + public static ShardKey none() { + return NONE; + } + + /** + * Create a new {@link ShardingStrategy#RANGE} shard key. + * + * @param propertyNames must not be {@literal null}. + * @return new instance of {@link ShardKey}. + */ + public static ShardKey range(String... propertyNames) { + return new ShardKey(Arrays.asList(propertyNames), ShardingStrategy.RANGE, false); + } + + /** + * Create a new {@link ShardingStrategy#RANGE} shard key. + * + * @param propertyNames must not be {@literal null}. + * @return new instance of {@link ShardKey}. + */ + public static ShardKey hash(String... propertyNames) { + return new ShardKey(Arrays.asList(propertyNames), ShardingStrategy.HASH, false); + } + + /** + * Turn the given {@link ShardKey} into an {@link #isImmutable() immutable} one. + * + * @param shardKey must not be {@literal null}. + * @return new instance of {@link ShardKey} if the given shard key is not already immutable. + */ + public static ShardKey immutable(ShardKey shardKey) { + + if (shardKey.isImmutable()) { + return shardKey; + } + + return new ShardKey(shardKey.propertyNames, shardKey.shardingStrategy, true); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java new file mode 100644 index 0000000000..646edfd6a1 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java @@ -0,0 +1,92 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.data.annotation.Persistent; + +/** + * The {@link Sharded} annotation provides meta information about the actual distribution of data across multiple + * machines. The {@link #shardKey()} is used to distribute documents across shards.
      + * Please visit the MongoDB Documentation for more information + * about requirements and limitations of sharding.
      + * Spring Data will automatically add the shard key to filter queries used for + * {@link com.mongodb.client.MongoCollection#replaceOne(org.bson.conversions.Bson, Object)} operations triggered by + * {@code save} operations on {@link org.springframework.data.mongodb.core.MongoOperations} and + * {@link org.springframework.data.mongodb.core.ReactiveMongoOperations} as well as {@code update/upsert} operation + * replacing/upserting a single existing document as long as the given + * {@link org.springframework.data.mongodb.core.query.UpdateDefinition} holds a full copy of the entity.
      + * All other operations that require the presence of the {@literal shard key} in the filter query need to provide the + * information via the {@link org.springframework.data.mongodb.core.query.Query} parameter when invoking the method. + * + * @author Christoph Strobl + * @since 3.0 + */ +@Persistent +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface Sharded { + + /** + * Alias for {@link #shardKey()}. + * + * @return {@literal _id} by default. + * @see #shardKey() + */ + @AliasFor("shardKey") + String[] value() default {}; + + /** + * The shard key determines the distribution of the collection’s documents among the cluster’s shards. The shard key + * is either a single or multiple indexed properties that exist in every document in the collection.
      + * By default the {@literal id} property is used for sharding.
      + * NOTE Required indexes will not be created automatically. Use + * {@link org.springframework.data.mongodb.core.index.Indexed} or + * {@link org.springframework.data.mongodb.core.index.CompoundIndex} along with enabled + * {@link org.springframework.data.mongodb.config.MongoConfigurationSupport#autoIndexCreation() auto index creation} + * or set up them up via + * {@link org.springframework.data.mongodb.core.index.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)}. + * + * @return an empty key by default. Which indicates to use the entities {@literal id} property. + */ + @AliasFor("value") + String[] shardKey() default {}; + + /** + * The sharding strategy to use for distributing data across sharded clusters. + * + * @return {@link ShardingStrategy#RANGE} by default + */ + ShardingStrategy shardingStrategy() default ShardingStrategy.RANGE; + + /** + * As of MongoDB 4.2 it is possible to change the shard key using update. Using immutable shard keys avoids server + * round trips to obtain an entities actual shard key from the database. + * + * @return {@literal false} by default; + * @see MongoDB + * Reference: Change a Document’s Shard Key Value + */ + boolean immutableKey() default false; + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java new file mode 100644 index 0000000000..922342c497 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java @@ -0,0 +1,35 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +public enum ShardingStrategy { + + /** + * Ranged sharding involves dividing data into ranges based on the shard key values. Each chunk is then assigned a + * range based on the shard key values. + */ + RANGE, + + /** + * Hashed Sharding involves computing a hash of the shard key field’s value. Each chunk is then assigned a range based + * on the hashed shard key values. + */ + HASH +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index 6ecd474d1f..7cd569ed47 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -54,13 +54,15 @@ public static T get(Bson bson, String key) { } public static Map asMap(Bson bson) { + if (bson instanceof Document) { return (Document) bson; } if (bson instanceof BasicDBObject) { return ((BasicDBObject) bson); } - throw new IllegalArgumentException("o_O what's that? Cannot read values from " + bson.getClass()); + + return (Map) bson.toBsonDocument(Document.class, MongoClientSettings.getDefaultCodecRegistry()); } public static void addToMap(Bson bson, String key, @Nullable Object value) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index c86eec5894..7f93fdc8e9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1829,6 +1829,95 @@ public void updateShouldMapAggregationUnsetToDomainType() { assertThat(captor.getValue()).isEqualTo(Collections.singletonList(Document.parse("{ $unset : \"firstname\" }"))); } + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyIfNotPresentInFilter() { + + template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + verify(collection).replaceOne(filter.capture(), any(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("country", "AT").append("userid", 4230)); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyToVersionedEntityIfNotPresentInFilter() { + + when(collection.replaceOne(any(), any(), any(ReplaceOptions.class))).thenReturn(UpdateResult.acknowledged(1, 1L, null)); + + template.save(new ShardedVersionedEntityWithNonDefaultShardKey("id-1", 1L, "AT", 4230)); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + verify(collection).replaceOne(filter.capture(), any(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("version", 1L).append("country", "AT").append("userid", 4230)); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyFromExistingDocumentIfNotPresentInFilter() { + + when(findIterable.first()).thenReturn(new Document("_id", "id-1").append("country", "US").append("userid", 4230)); + + template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + ArgumentCaptor replacement = ArgumentCaptor.forClass(Document.class); + + verify(collection).replaceOne(filter.capture(), replacement.capture(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("country", "US").append("userid", 4230)); + assertThat(replacement.getValue()).containsEntry("country", "AT").containsEntry("userid", 4230); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyFromGivenDocumentIfShardKeyIsImmutable() { + + template.save(new ShardedEntityWithNonDefaultImmutableShardKey("id-1", "AT", 4230)); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + ArgumentCaptor replacement = ArgumentCaptor.forClass(Document.class); + + verify(collection).replaceOne(filter.capture(), replacement.capture(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("country", "AT").append("userid", 4230)); + assertThat(replacement.getValue()).containsEntry("country", "AT").containsEntry("userid", 4230); + + verifyNoInteractions(findIterable); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendDefaultShardKeyIfNotPresentInFilter() { + + template.save(new ShardedEntityWithDefaultShardKey("id-1", "AT", 4230)); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + verify(collection).replaceOne(filter.capture(), any(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1")); + verify(findIterable, never()).first(); + } + + @Test // DATAMONGO-2341 + void saveShouldProjectOnShardKeyWhenLoadingExistingDocument() { + + when(findIterable.first()).thenReturn(new Document("_id", "id-1").append("country", "US").append("userid", 4230)); + + template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)); + + verify(findIterable).projection(new Document("country", 1).append("userid", 1)); + } + + @Test // DATAMONGO-2341 + void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { + + when(collection.replaceOne(any(), any(), any(ReplaceOptions.class))).thenReturn(UpdateResult.acknowledged(1, 1L, null)); + when(findIterable.first()).thenReturn(new Document("_id", "id-1").append("country", "US").append("userid", 4230)); + + template.save(new ShardedVersionedEntityWithNonDefaultShardKey("id-1", 1L, "AT", 4230)); + + verify(findIterable).projection(new Document("country", 1).append("userid", 1)); + } + class AutogenerateableId { @Id BigInteger id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index f48d81bb62..240fdb6c3a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; +import static org.springframework.data.mongodb.test.util.Assertions.assertThat; import lombok.Data; import reactor.core.publisher.Mono; @@ -999,6 +1000,101 @@ public void updateShouldMapAggregationUnsetToDomainType() { assertThat(captor.getValue()).isEqualTo(Collections.singletonList(Document.parse("{ $unset : \"firstname\" }"))); } + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyIfNotPresentInFilter() { + + when(findPublisher.first()).thenReturn(Mono.empty()); + + template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)).subscribe(); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + verify(collection).replaceOne(filter.capture(), any(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("country", "AT").append("userid", 4230)); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyFromGivenDocumentIfShardKeyIsImmutable() { + + template.save(new ShardedEntityWithNonDefaultImmutableShardKey("id-1", "AT", 4230)).subscribe(); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + ArgumentCaptor replacement = ArgumentCaptor.forClass(Document.class); + + verify(collection).replaceOne(filter.capture(), replacement.capture(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("country", "AT").append("userid", 4230)); + assertThat(replacement.getValue()).containsEntry("country", "AT").containsEntry("userid", 4230); + + verifyNoInteractions(findPublisher); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyToVersionedEntityIfNotPresentInFilter() { + + when(collection.replaceOne(any(Bson.class), any(Document.class), any(ReplaceOptions.class))) + .thenReturn(Mono.just(UpdateResult.acknowledged(1, 1L, null))); + when(findPublisher.first()).thenReturn(Mono.empty()); + + template.save(new ShardedVersionedEntityWithNonDefaultShardKey("id-1", 1L, "AT", 4230)).subscribe(); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + verify(collection).replaceOne(filter.capture(), any(), any()); + + assertThat(filter.getValue()) + .isEqualTo(new Document("_id", "id-1").append("version", 1L).append("country", "AT").append("userid", 4230)); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendNonDefaultShardKeyFromExistingDocumentIfNotPresentInFilter() { + + when(findPublisher.first()) + .thenReturn(Mono.just(new Document("_id", "id-1").append("country", "US").append("userid", 4230))); + + template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)).subscribe(); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + ArgumentCaptor replacement = ArgumentCaptor.forClass(Document.class); + + verify(collection).replaceOne(filter.capture(), replacement.capture(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("country", "US").append("userid", 4230)); + assertThat(replacement.getValue()).containsEntry("country", "AT").containsEntry("userid", 4230); + } + + @Test // DATAMONGO-2341 + void saveShouldAppendDefaultShardKeyIfNotPresentInFilter() { + + template.save(new ShardedEntityWithDefaultShardKey("id-1", "AT", 4230)).subscribe(); + + ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); + verify(collection).replaceOne(filter.capture(), any(), any()); + + assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1")); + } + + @Test // DATAMONGO-2341 + void saveShouldProjectOnShardKeyWhenLoadingExistingDocument() { + + when(findPublisher.first()).thenReturn(Mono.just(new Document("_id", "id-1").append("country", "US").append("userid", 4230))); + + template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)).subscribe(); + + verify(findPublisher).projection(new Document("country", 1).append("userid", 1)); + } + + @Test // DATAMONGO-2341 + void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { + + when(collection.replaceOne(any(Bson.class), any(Document.class), any(ReplaceOptions.class))) + .thenReturn(Mono.just(UpdateResult.acknowledged(1, 1L, null))); + when(findPublisher.first()).thenReturn(Mono.empty()); + + template.save(new ShardedVersionedEntityWithNonDefaultShardKey("id-1", 1L, "AT", 4230)).subscribe(); + + verify(findPublisher).projection(new Document("country", 1).append("userid", 1)); + } + @Data @org.springframework.data.mongodb.core.mapping.Document(collection = "star-wars") static class Person { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithDefaultShardKey.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithDefaultShardKey.java new file mode 100644 index 0000000000..0f8413e88c --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithDefaultShardKey.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 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 + * + * https://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 lombok.AllArgsConstructor; +import lombok.Data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.Sharded; + +/** + * @author Christoph Strobl + */ +@Data +@AllArgsConstructor +@Sharded +public class ShardedEntityWithDefaultShardKey { + + private @Id String id; + + private String country; + + @Field("userid") // + private Integer userId; + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultImmutableShardKey.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultImmutableShardKey.java new file mode 100644 index 0000000000..85e97d5be7 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultImmutableShardKey.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 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 + * + * https://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 lombok.AllArgsConstructor; +import lombok.Data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.Sharded; + +/** + * @author Christoph Strobl + */ +@Data +@AllArgsConstructor +@Sharded(shardKey = { "country", "userId" }, immutableKey = true) +public class ShardedEntityWithNonDefaultImmutableShardKey { + + private @Id String id; + + private String country; + + @Field("userid") // + private Integer userId; + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultShardKey.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultShardKey.java new file mode 100644 index 0000000000..2aa4243602 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedEntityWithNonDefaultShardKey.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 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 + * + * https://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 lombok.AllArgsConstructor; +import lombok.Data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.Sharded; + +/** + * @author Christoph Strobl + */ +@Data +@AllArgsConstructor +@Sharded(shardKey = { "country", "userId" }) +public class ShardedEntityWithNonDefaultShardKey { + + private @Id String id; + + private String country; + + @Field("userid") // + private Integer userId; + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedVersionedEntityWithNonDefaultShardKey.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedVersionedEntityWithNonDefaultShardKey.java new file mode 100644 index 0000000000..e0b07885a6 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ShardedVersionedEntityWithNonDefaultShardKey.java @@ -0,0 +1,43 @@ +/* + * Copyright 2020 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 + * + * https://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 lombok.AllArgsConstructor; +import lombok.Data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.Sharded; + +/** + * @author Christoph Strobl + */ +@Data +@AllArgsConstructor +@Sharded(shardKey = { "country", "userId" }) +public class ShardedVersionedEntityWithNonDefaultShardKey { + + private @Id String id; + + private @Version Long version; + + private String country; + + @Field("userid") // + private Integer userId; + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java new file mode 100644 index 0000000000..8edffec3e1 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java @@ -0,0 +1,150 @@ +/* + * Copyright 2020 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 + * + * https://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.*; + +import java.util.Arrays; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.CodecRegistryProvider; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.convert.UpdateMapper; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import com.mongodb.MongoClientSettings; + +/** + * @author Christoph Strobl + */ +class UpdateOperationsUnitTests { + + static final Document SHARD_KEY = new Document("country", "AT").append("userid", "4230"); + static final Document SOURCE_DOC = appendShardKey(new Document("_id", "id-1")); + + MongoMappingContext mappingContext = new MongoMappingContext(); + MongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); + QueryMapper queryMapper = new QueryMapper(mongoConverter); + UpdateMapper updateMapper = new UpdateMapper(mongoConverter); + EntityOperations entityOperations = new EntityOperations(mappingContext); + + ExtendedQueryOperations queryOperations = new ExtendedQueryOperations(queryMapper, updateMapper, entityOperations, + MongoClientSettings::getDefaultCodecRegistry); + + @Test // DATAMONGO-2341 + void appliesShardKeyToFilter() { + + Document sourceFilter = new Document("name", "kaladin"); + assertThat(shardedFilter(sourceFilter, ShardedEntityWithNonDefaultShardKey.class, null)) + .isEqualTo(appendShardKey(sourceFilter)); + } + + @Test + void applyShardKeyDoesNotAlterSourceFilter() { + + Document sourceFilter = new Document("name", "kaladin"); + shardedFilter(sourceFilter, ShardedEntityWithNonDefaultShardKey.class, null); + assertThat(sourceFilter).isEqualTo(new Document("name", "kaladin")); + } + + @Test // DATAMONGO-2341 + void appliesExistingShardKeyToFilter() { + + Document sourceFilter = new Document("name", "kaladin"); + Document existing = new Document("country", "GB").append("userid", "007"); + + assertThat(shardedFilter(sourceFilter, ShardedEntityWithNonDefaultShardKey.class, existing)) + .isEqualTo(new Document(existing).append("name", "kaladin")); + } + + @Test // DATAMONGO-2341 + void recognizesExistingShardKeyInFilter() { + + Document sourceFilter = appendShardKey(new Document("name", "kaladin")); + + assertThat(queryOperations.replaceSingleContextFor(SOURCE_DOC).requiresShardKey(sourceFilter, + entityOf(ShardedEntityWithNonDefaultShardKey.class))).isFalse(); + } + + @Test // DATAMONGO-2341 + void recognizesIdPropertyAsShardKey() { + + Document sourceFilter = new Document("_id", "id-1"); + + assertThat(queryOperations.replaceSingleContextFor(SOURCE_DOC).requiresShardKey(sourceFilter, + entityOf(ShardedEntityWithDefaultShardKey.class))).isFalse(); + } + + @Test // DATAMONGO-2341 + void returnsMappedShardKey() { + + queryOperations.replaceSingleContextFor(SOURCE_DOC) + .getMappedShardKeyFields(entityOf(ShardedEntityWithDefaultShardKey.class)) + .containsAll(Arrays.asList("country", "userid")); + } + + @NonNull + private Document shardedFilter(Document sourceFilter, Class entity, Document existing) { + return queryOperations.replaceSingleContextFor(SOURCE_DOC).applyShardKey(entity, sourceFilter, existing); + } + + private static Document appendShardKey(Document source) { + + Document target = new Document(source); + target.putAll(SHARD_KEY); + return target; + } + + MongoPersistentEntity entityOf(Class type) { + return mappingContext.getPersistentEntity(type); + } + + class ExtendedQueryOperations extends QueryOperations { + + ExtendedQueryOperations(QueryMapper queryMapper, UpdateMapper updateMapper, EntityOperations entityOperations, + CodecRegistryProvider codecRegistryProvider) { + super(queryMapper, updateMapper, entityOperations, codecRegistryProvider); + } + + @NonNull + private ExtendedUpdateContext replaceSingleContextFor(Document source) { + return new ExtendedUpdateContext(MappedDocument.of(source), true); + } + + MongoPersistentEntity entityOf(Class type) { + return mappingContext.getPersistentEntity(type); + } + + class ExtendedUpdateContext extends UpdateContext { + + ExtendedUpdateContext(MappedDocument update, boolean upsert) { + super(update, upsert); + } + + Document applyShardKey(@Nullable Class domainType, Document filter, @Nullable Document existing) { + return applyShardKey(entityOf(domainType), filter, existing); + } + } + + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java index 70c3b9767c..07100b9405 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java @@ -255,6 +255,38 @@ public void readsDocumentCollation() { assertThat(entity.getCollation()).isEqualTo(org.springframework.data.mongodb.core.query.Collation.of("en_US")); } + @Test // DATAMONGO-2341 + public void detectsShardedEntityCorrectly() { + + assertThat(entityOf(WithDefaultShardKey.class).isSharded()).isTrue(); + assertThat(entityOf(Contact.class).isSharded()).isFalse(); + } + + @Test // DATAMONGO-2341 + public void readsDefaultShardKey() { + + assertThat(entityOf(WithDefaultShardKey.class).getShardKey().getDocument()) + .isEqualTo(new org.bson.Document("_id", 1)); + } + + @Test // DATAMONGO-2341 + public void readsSingleShardKey() { + + assertThat(entityOf(WithSingleShardKey.class).getShardKey().getDocument()) + .isEqualTo(new org.bson.Document("country", 1)); + } + + @Test // DATAMONGO-2341 + public void readsMultiShardKey() { + + assertThat(entityOf(WithMultiShardKey.class).getShardKey().getDocument()) + .isEqualTo(new org.bson.Document("country", 1).append("userid", 1)); + } + + static BasicMongoPersistentEntity entityOf(Class type) { + return new BasicMongoPersistentEntity<>(ClassTypeInformation.from(type)); + } + @Document("contacts") class Contact {} @@ -313,6 +345,15 @@ class WithSimpleCollation {} @Document(collation = "{ 'locale' : 'en_US' }") class WithDocumentCollation {} + @Sharded + class WithDefaultShardKey {} + + @Sharded("country") + class WithSingleShardKey {} + + @Sharded({ "country", "userid" }) + class WithMultiShardKey {} + static class SampleExtension implements EvaluationContextExtension { /* diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 11533441ba..12a4390423 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -30,6 +30,7 @@ include::reference/reactive-mongo-repositories.adoc[leveloffset=+1] include::{spring-data-commons-docs}/auditing.adoc[leveloffset=+1] include::reference/mongo-auditing.adoc[leveloffset=+1] include::reference/mapping.adoc[leveloffset=+1] +include::reference/sharding.adoc[leveloffset=+1] include::reference/kotlin.adoc[leveloffset=+1] include::reference/cross-store.adoc[leveloffset=+1] include::reference/jmx.adoc[leveloffset=+1] diff --git a/src/main/asciidoc/reference/sharding.adoc b/src/main/asciidoc/reference/sharding.adoc new file mode 100644 index 0000000000..2ca3713a21 --- /dev/null +++ b/src/main/asciidoc/reference/sharding.adoc @@ -0,0 +1,70 @@ +[[sharding]] += Sharding + +MongoDB supports large data sets via sharding, a method for distributing data across multiple machines. Please refer to the https://docs.mongodb.com/manual/sharding/[MongoDB Documentation] to learn how to set up a sharded cluster, its requirements and limitations. + +Spring Data MongoDB uses the `@Sharded` annotation to identify entities stored in sharded collections as shown below. + +==== +[source, java] +---- +@Document("users") +@Sharded(shardKey = { "country", "userId" }) <1> +public class User { + + @Id + Long id; + + @Field("userid") + String userId; + + String country; +} +---- +<1> The properties of the shard key are mapped to the actual field names. See +==== + +[[sharding.sharded-collections]] +== Sharded Collections + +Spring Data MongoDB does not auto set up sharding for collections nor indexes required for it. The snippet below shows how to do so using the MongoDB client API. + +==== +[source, java] +---- +MongoDatabase adminDB = template.getMongoDbFactory() + .getMongoDatabase("admin"); <1> + +adminDB.runCommand(new Document("enableSharding", "db")); <2> + +Document shardCmd = new Document("shardCollection", "db.users") <3> + .append("key", new Document("country", 1).append("userid", 1)); <4> + +adminDB.runCommand(shardCmd); +---- +<1> Sharding commands need to be run against the _admin_ database. +<2> Enable sharding for a specific database if necessary. +<3> Shard a collection within the database having sharding enabled. +<4> Set the shard key (Range based sharding in this case). +==== + +[[sharding.shard-key]] +== Shard Key Handling + +The shard key consists of a single or multiple properties present in every document within the target collection, and is used to distribute them across shards. + +Adding the `@Sharded` annotation to an entity enables Spring Data MongoDB to do best effort optimisations required for sharded scenarios when using repositories. +This means essentially adding required shard key information, if not already present, to `replaceOne` filter queries when upserting entities. This may require an additional server round trip to determine the actual value of the current shard key. + +TIP: By setting `@Sharded(immutableKey = true)` no attempt will be made to check if an entities shard key changed. + +Please see the https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#upsert[MongoDB Documentation] for further details and the list below for which operations are eligible for auto include the shard key. + +* `Reactive/CrudRepository.save(...)` +* `Reactive/CrudRepository.saveAll(...)` +* `Reactive/MongoTemplate.save(...)` + + + + + From 22ca597fcaf51a1ca2fa2dc687701d32f690a543 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 17 Feb 2020 10:11:26 +0100 Subject: [PATCH 0084/1381] DATAMONGO-2341 - Polishing. Inline MongoPersistentEntity.idPropertyIsShardKey() into UpdateContext. Move mapped shard key cache to QueryOperations level. Simplify conditionals. Tweak documentation. Original pull request: #833. --- .../data/mongodb/core/MongoTemplate.java | 2 +- .../data/mongodb/core/QueryOperations.java | 44 ++++++++++++------- .../mongodb/core/ReactiveMongoTemplate.java | 31 +++++++------ .../mapping/BasicMongoPersistentEntity.java | 41 +++++++++-------- .../core/mapping/MongoPersistentEntity.java | 22 +--------- .../data/mongodb/core/mapping/ShardKey.java | 18 ++++++-- .../data/mongodb/core/mapping/Sharded.java | 39 ++++++++-------- .../mongodb/core/MongoTemplateUnitTests.java | 9 ++-- .../core/ReactiveMongoTemplateUnitTests.java | 3 +- .../core/UpdateOperationsUnitTests.java | 5 ++- src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/reference/sharding.adoc | 40 ++++++++++------- 12 files changed, 138 insertions(+), 117 deletions(-) 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 4179c0f67b..07a4e2bd63 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 @@ -1640,7 +1640,7 @@ protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefini collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()); } } - + ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass); return collection.replaceOne(filter, updateObj, replaceOptions); } else { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index f6852c3337..357f1bddec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -40,6 +40,7 @@ import org.springframework.data.mongodb.core.convert.UpdateMapper; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.core.mapping.ShardKey; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Query; @@ -58,9 +59,10 @@ /** * {@link QueryOperations} centralizes common operations required before an operation is actually ready to be executed. * This involves mapping {@link Query queries} into their respective MongoDB representation, computing execution options - * for {@literal count}, {@literal remove}, ...
      + * for {@literal count}, {@literal remove}, and other methods. * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ class QueryOperations { @@ -71,6 +73,7 @@ class QueryOperations { private final CodecRegistryProvider codecRegistryProvider; private final MappingContext, MongoPersistentProperty> mappingContext; private final AggregationUtil aggregationUtil; + private final Map, Document> mappedShardKey = new ConcurrentHashMap<>(1); /** * Create a new instance of {@link QueryOperations}. @@ -503,7 +506,6 @@ class UpdateContext extends QueryContext { private final boolean upsert; private final @Nullable UpdateDefinition update; private final @Nullable MappedDocument mappedDocument; - private final Map, Document> mappedShardKey = new ConcurrentHashMap<>(1); /** * Create a new {@link UpdateContext} instance. @@ -624,41 +626,49 @@ Document getMappedQuery(@Nullable MongoPersistentEntity domainType) { return mappedQuery; } - Document applyShardKey(@Nullable MongoPersistentEntity domainType, Document filter, - @Nullable Document existing) { + Document applyShardKey(MongoPersistentEntity domainType, Document filter, @Nullable Document existing) { Document shardKeySource = existing != null ? existing : mappedDocument != null ? mappedDocument.getDocument() : getMappedUpdate(domainType); Document filterWithShardKey = new Document(filter); - for (String key : getMappedShardKeyFields(domainType)) { - if (!filterWithShardKey.containsKey(key)) { - filterWithShardKey.append(key, shardKeySource.get(key)); - } - } + getMappedShardKeyFields(domainType).forEach(key -> filterWithShardKey.putIfAbsent(key, shardKeySource.get(key))); return filterWithShardKey; } - boolean requiresShardKey(Document filter, @Nullable MongoPersistentEntity domainType) { + boolean requiresShardKey(Document filter, @Nullable MongoPersistentEntity domainType) { - if (multi || domainType == null || !domainType.isSharded() || domainType.idPropertyIsShardKey()) { + return !multi && domainType != null && domainType.isSharded() && !shardedById(domainType) + && !filter.keySet().containsAll(getMappedShardKeyFields(domainType)); + } + + /** + * @return {@literal true} if the {@link MongoPersistentEntity#getShardKey() shard key} is the entities + * {@literal id} property. + * @since 3.0 + */ + private boolean shardedById(MongoPersistentEntity domainType) { + + ShardKey shardKey = domainType.getShardKey(); + if (shardKey.size() != 1) { return false; } - if (filter.keySet().containsAll(getMappedShardKeyFields(domainType))) { - return false; + String key = shardKey.getPropertyNames().iterator().next(); + if ("_id".equals(key)) { + return true; } - return true; + MongoPersistentProperty idProperty = domainType.getIdProperty(); + return idProperty != null && idProperty.getName().equals(key); } - Set getMappedShardKeyFields(@Nullable MongoPersistentEntity entity) { + Set getMappedShardKeyFields(MongoPersistentEntity entity) { return getMappedShardKey(entity).keySet(); } - Document getMappedShardKey(@Nullable MongoPersistentEntity entity) { - + Document getMappedShardKey(MongoPersistentEntity entity) { return mappedShardKey.computeIfAbsent(entity.getType(), key -> queryMapper.getMappedFields(entity.getShardKey().getDocument(), entity)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index b2324f94f0..b2f4571324 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -1637,7 +1637,7 @@ protected Mono saveDocument(String collectionName, Document document, Cl ? collection // : collection.withWriteConcern(writeConcernToUse); - Publisher publisher = null; + Publisher publisher; if (!mapped.hasId()) { publisher = collectionToUse.insertOne(document); } else { @@ -1647,20 +1647,23 @@ protected Mono saveDocument(String collectionName, Document document, Cl Document filter = updateContext.getMappedQuery(entity); Document replacement = updateContext.getMappedUpdate(entity); - Mono theFilter = Mono.just(filter); + Mono deferredFilter; - if(updateContext.requiresShardKey(filter, entity)) { + if (updateContext.requiresShardKey(filter, entity)) { if (entity.getShardKey().isImmutable()) { - theFilter = Mono.just(updateContext.applyShardKey(entity, filter, null)); + deferredFilter = Mono.just(updateContext.applyShardKey(entity, filter, null)); } else { - theFilter = Mono.from( - collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()) + deferredFilter = Mono + .from( + collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()) .defaultIfEmpty(replacement).map(it -> updateContext.applyShardKey(entity, filter, it)); } + } else { + deferredFilter = Mono.just(filter); } - publisher = theFilter.flatMap( - it -> Mono.from(collectionToUse.replaceOne(it, replacement, updateContext.getReplaceOptions(entityClass)))); + publisher = deferredFilter.flatMapMany( + it -> collectionToUse.replaceOne(it, replacement, updateContext.getReplaceOptions(entityClass))); } return Mono.from(publisher).map(o -> mapped.getId()); @@ -1800,20 +1803,22 @@ protected Mono doUpdate(String collectionName, Query query, @Nulla if (!UpdateMapper.isUpdateObject(updateObj)) { Document filter = new Document(queryObj); - Mono theFilter = Mono.just(filter); + Mono deferredFilter; - if(updateContext.requiresShardKey(filter, entity)) { + if (updateContext.requiresShardKey(filter, entity)) { if (entity.getShardKey().isImmutable()) { - theFilter = Mono.just(updateContext.applyShardKey(entity, filter, null)); + deferredFilter = Mono.just(updateContext.applyShardKey(entity, filter, null)); } else { - theFilter = Mono.from( + deferredFilter = Mono.from( collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()) .defaultIfEmpty(updateObj).map(it -> updateContext.applyShardKey(entity, filter, it)); } + } else { + deferredFilter = Mono.just(filter); } ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass); - return theFilter.flatMap(it -> Mono.from(collectionToUse.replaceOne(it, updateObj, replaceOptions))); + return deferredFilter.flatMap(it -> Mono.from(collectionToUse.replaceOne(it, updateObj, replaceOptions))); } return multi ? collectionToUse.updateMany(queryObj, updateObj, updateOptions) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index cbc67b13ab..3a9fa8a668 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -96,7 +96,26 @@ public BasicMongoPersistentEntity(TypeInformation typeInformation) { this.collationExpression = null; } - this.shardKey = detectShardKey(this); + this.shardKey = detectShardKey(); + } + + private ShardKey detectShardKey() { + + if (!isAnnotationPresent(Sharded.class)) { + return ShardKey.none(); + } + + Sharded sharded = getRequiredAnnotation(Sharded.class); + + String[] keyProperties = sharded.shardKey(); + if (ObjectUtils.isEmpty(keyProperties)) { + keyProperties = new String[] { "_id" }; + } + + ShardKey shardKey = ShardingStrategy.HASH.equals(sharded.shardingStrategy()) ? ShardKey.hash(keyProperties) + : ShardKey.range(keyProperties); + + return sharded.immutableKey() ? ShardKey.immutable(shardKey) : shardKey; } /* @@ -307,26 +326,6 @@ private static Expression detectExpression(@Nullable String potentialExpression) return expression instanceof LiteralExpression ? null : expression; } - @Nullable - private static ShardKey detectShardKey(BasicMongoPersistentEntity entity) { - - if (!entity.isAnnotationPresent(Sharded.class)) { - return ShardKey.none(); - } - - Sharded sharded = entity.getRequiredAnnotation(Sharded.class); - - String[] keyProperties = sharded.shardKey(); - if (ObjectUtils.isEmpty(keyProperties)) { - keyProperties = new String[] { "_id" }; - } - - ShardKey shardKey = ShardingStrategy.HASH.equals(sharded.shardingStrategy()) ? ShardKey.hash(keyProperties) - : ShardKey.range(keyProperties); - - return sharded.immutableKey() ? ShardKey.immutable(shardKey) : shardKey; - } - /** * Handler to collect {@link MongoPersistentProperty} instances and check that each of them is mapped to a distinct * field name. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java index 1cef658d98..b5a3afc41c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java @@ -86,29 +86,11 @@ default boolean hasCollation() { ShardKey getShardKey(); /** - * @return {@literal true} if the {@link #getShardKey() shard key} does not match {@link ShardKey#none()}. + * @return {@literal true} if the {@link #getShardKey() shard key} is sharded. * @since 3.0 */ default boolean isSharded() { - return !ShardKey.none().equals(getShardKey()); + return getShardKey().isSharded(); } - /** - * @return {@literal true} if the {@link #getShardKey() shard key} is the entities {@literal id} property. - * @since 3.0 - */ - default boolean idPropertyIsShardKey() { - - ShardKey shardKey = getShardKey(); - if (shardKey.size() != 1) { - return false; - } - String key = shardKey.getPropertyNames().iterator().next(); - if ("_id".equals(key)) { - return true; - } - - MongoPersistentProperty idProperty = getIdProperty(); - return idProperty != null && idProperty.getName().equals(key); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java index 67ebf193da..2a93205244 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java @@ -28,12 +28,13 @@ * Value object representing an entities Shard * Key used to distribute documents across a sharded MongoDB cluster. *

      - * {@link ShardKey#isImmutable() Immutable} shard keys indicate a fixed value that is not updated (see + * {@link ShardKey#isImmutable() Immutable} shard keys indicates a fixed value that is not updated (see * MongoDB - * Reference: Change a Document’s Shard Key Value), which allows to skip server round trips in cases where a + * Reference: Change a Document's Shard Key Value), which allows to skip server round trips in cases where a * potential shard key change might have occurred. * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ public class ShardKey { @@ -68,14 +69,23 @@ public Collection getPropertyNames() { /** * @return {@literal true} if the shard key of an document does not change. * @see MongoDB - * Reference: Change a Document’s Shard Key Value + * Reference: Change a Document's Shard Key Value */ public boolean isImmutable() { return immutable; } /** - * Get the unmapped MongoDB representation of the {@link ShardKey}. + * Return whether the shard key represents a sharded key. Return {@literal false} if the key is not sharded. + * + * @return {@literal true} if the key is sharded; {@literal false} otherwise. + */ + public boolean isSharded() { + return !propertyNames.isEmpty(); + } + + /** + * Get the raw MongoDB representation of the {@link ShardKey}. * * @return never {@literal null}. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java index 646edfd6a1..514475982a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java @@ -25,26 +25,29 @@ import org.springframework.data.annotation.Persistent; /** - * The {@link Sharded} annotation provides meta information about the actual distribution of data across multiple - * machines. The {@link #shardKey()} is used to distribute documents across shards.
      - * Please visit the MongoDB Documentation for more information - * about requirements and limitations of sharding.
      - * Spring Data will automatically add the shard key to filter queries used for + * The {@link Sharded} annotation provides meta information about the actual distribution of data. The + * {@link #shardKey()} is used to distribute documents across shards.
      + * Please see the MongoDB Documentation for more information + * about requirements and limitations of sharding. + *

      + * Spring Data adds the shard key to filter queries used for * {@link com.mongodb.client.MongoCollection#replaceOne(org.bson.conversions.Bson, Object)} operations triggered by * {@code save} operations on {@link org.springframework.data.mongodb.core.MongoOperations} and - * {@link org.springframework.data.mongodb.core.ReactiveMongoOperations} as well as {@code update/upsert} operation + * {@link org.springframework.data.mongodb.core.ReactiveMongoOperations} as well as {@code update/upsert} operations * replacing/upserting a single existing document as long as the given - * {@link org.springframework.data.mongodb.core.query.UpdateDefinition} holds a full copy of the entity.
      + * {@link org.springframework.data.mongodb.core.query.UpdateDefinition} holds a full copy of the entity. + *

      * All other operations that require the presence of the {@literal shard key} in the filter query need to provide the * information via the {@link org.springframework.data.mongodb.core.query.Query} parameter when invoking the method. * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ @Persistent @Inherited @Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.TYPE }) +@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) public @interface Sharded { /** @@ -57,15 +60,15 @@ String[] value() default {}; /** - * The shard key determines the distribution of the collection’s documents among the cluster’s shards. The shard key - * is either a single or multiple indexed properties that exist in every document in the collection.
      + * The shard key determines the distribution of the collection's documents among the cluster's shards. The shard key + * is either a single or multiple indexed properties that exist in every document in the collection. + *

      * By default the {@literal id} property is used for sharding.
      - * NOTE Required indexes will not be created automatically. Use - * {@link org.springframework.data.mongodb.core.index.Indexed} or + * NOTE Required indexes are not created automatically. Create these either externally, via + * {@link org.springframework.data.mongodb.core.index.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)} + * or by annotating your domain model with {@link org.springframework.data.mongodb.core.index.Indexed}/ * {@link org.springframework.data.mongodb.core.index.CompoundIndex} along with enabled - * {@link org.springframework.data.mongodb.config.MongoConfigurationSupport#autoIndexCreation() auto index creation} - * or set up them up via - * {@link org.springframework.data.mongodb.core.index.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)}. + * {@link org.springframework.data.mongodb.config.MongoConfigurationSupport#autoIndexCreation() auto index creation}. * * @return an empty key by default. Which indicates to use the entities {@literal id} property. */ @@ -82,10 +85,10 @@ /** * As of MongoDB 4.2 it is possible to change the shard key using update. Using immutable shard keys avoids server * round trips to obtain an entities actual shard key from the database. - * - * @return {@literal false} by default; + * + * @return {@literal false} by default. * @see MongoDB - * Reference: Change a Document’s Shard Key Value + * Reference: Change a Document's Shard Key Value */ boolean immutableKey() default false; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 7f93fdc8e9..3d87afad8b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1843,14 +1843,16 @@ void saveShouldAppendNonDefaultShardKeyIfNotPresentInFilter() { @Test // DATAMONGO-2341 void saveShouldAppendNonDefaultShardKeyToVersionedEntityIfNotPresentInFilter() { - when(collection.replaceOne(any(), any(), any(ReplaceOptions.class))).thenReturn(UpdateResult.acknowledged(1, 1L, null)); + when(collection.replaceOne(any(), any(), any(ReplaceOptions.class))) + .thenReturn(UpdateResult.acknowledged(1, 1L, null)); template.save(new ShardedVersionedEntityWithNonDefaultShardKey("id-1", 1L, "AT", 4230)); ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); verify(collection).replaceOne(filter.capture(), any(), any()); - assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("version", 1L).append("country", "AT").append("userid", 4230)); + assertThat(filter.getValue()) + .isEqualTo(new Document("_id", "id-1").append("version", 1L).append("country", "AT").append("userid", 4230)); } @Test // DATAMONGO-2341 @@ -1910,7 +1912,8 @@ void saveShouldProjectOnShardKeyWhenLoadingExistingDocument() { @Test // DATAMONGO-2341 void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { - when(collection.replaceOne(any(), any(), any(ReplaceOptions.class))).thenReturn(UpdateResult.acknowledged(1, 1L, null)); + when(collection.replaceOne(any(), any(), any(ReplaceOptions.class))) + .thenReturn(UpdateResult.acknowledged(1, 1L, null)); when(findIterable.first()).thenReturn(new Document("_id", "id-1").append("country", "US").append("userid", 4230)); template.save(new ShardedVersionedEntityWithNonDefaultShardKey("id-1", 1L, "AT", 4230)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 240fdb6c3a..e34f4922cc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -1076,7 +1076,8 @@ void saveShouldAppendDefaultShardKeyIfNotPresentInFilter() { @Test // DATAMONGO-2341 void saveShouldProjectOnShardKeyWhenLoadingExistingDocument() { - when(findPublisher.first()).thenReturn(Mono.just(new Document("_id", "id-1").append("country", "US").append("userid", 4230))); + when(findPublisher.first()) + .thenReturn(Mono.just(new Document("_id", "id-1").append("country", "US").append("userid", 4230))); template.save(new ShardedEntityWithNonDefaultShardKey("id-1", "AT", 4230)).subscribe(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java index 8edffec3e1..26eee53bf3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java @@ -35,6 +35,8 @@ import com.mongodb.MongoClientSettings; /** + * Unit test for {@link com.mongodb.internal.operation.UpdateOperation}. + * * @author Christoph Strobl */ class UpdateOperationsUnitTests { @@ -141,10 +143,9 @@ class ExtendedUpdateContext extends UpdateContext { super(update, upsert); } - Document applyShardKey(@Nullable Class domainType, Document filter, @Nullable Document existing) { + Document applyShardKey(Class domainType, Document filter, @Nullable Document existing) { return applyShardKey(entityOf(domainType), filter, existing); } } - } } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index afa253e62b..dc84a60935 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -8,6 +8,7 @@ * Support for <>. * Removal of `_id` flattening for composite Id's when using `MongoTemplate` aggregations. * Apply pagination when using GridFS `find(Query)`. +* <> via `@Sharded`. [[new-features.2-2-0]] == What's New in Spring Data MongoDB 2.2 diff --git a/src/main/asciidoc/reference/sharding.adoc b/src/main/asciidoc/reference/sharding.adoc index 2ca3713a21..8678dc2178 100644 --- a/src/main/asciidoc/reference/sharding.adoc +++ b/src/main/asciidoc/reference/sharding.adoc @@ -1,12 +1,13 @@ [[sharding]] = Sharding -MongoDB supports large data sets via sharding, a method for distributing data across multiple machines. Please refer to the https://docs.mongodb.com/manual/sharding/[MongoDB Documentation] to learn how to set up a sharded cluster, its requirements and limitations. +MongoDB supports large data sets via sharding, a method for distributing data across multiple database servers. +Please refer to the https://docs.mongodb.com/manual/sharding/[MongoDB Documentation] to learn how to set up a sharded cluster, its requirements and limitations. Spring Data MongoDB uses the `@Sharded` annotation to identify entities stored in sharded collections as shown below. ==== -[source, java] +[source,java] ---- @Document("users") @Sharded(shardKey = { "country", "userId" }) <1> @@ -21,23 +22,24 @@ public class User { String country; } ---- -<1> The properties of the shard key are mapped to the actual field names. See +<1> The properties of the shard key get mapped to the actual field names. ==== [[sharding.sharded-collections]] == Sharded Collections -Spring Data MongoDB does not auto set up sharding for collections nor indexes required for it. The snippet below shows how to do so using the MongoDB client API. +Spring Data MongoDB does not auto set up sharding for collections nor indexes required for it. +The snippet below shows how to do so using the MongoDB client API. ==== -[source, java] +[source,java] ---- MongoDatabase adminDB = template.getMongoDbFactory() - .getMongoDatabase("admin"); <1> + .getMongoDatabase("admin"); <1> -adminDB.runCommand(new Document("enableSharding", "db")); <2> +adminDB.runCommand(new Document("enableSharding", "db")); <2> -Document shardCmd = new Document("shardCollection", "db.users") <3> +Document shardCmd = new Document("shardCollection", "db.users") <3> .append("key", new Document("country", 1).append("userid", 1)); <4> adminDB.runCommand(shardCmd); @@ -45,24 +47,28 @@ adminDB.runCommand(shardCmd); <1> Sharding commands need to be run against the _admin_ database. <2> Enable sharding for a specific database if necessary. <3> Shard a collection within the database having sharding enabled. -<4> Set the shard key (Range based sharding in this case). +<4> Specify the shard key. +This example uses range based sharding. ==== [[sharding.shard-key]] == Shard Key Handling -The shard key consists of a single or multiple properties present in every document within the target collection, and is used to distribute them across shards. +The shard key consists of a single or multiple properties that must exist in every document in the target collection. +It is used to distribute documents across shards. -Adding the `@Sharded` annotation to an entity enables Spring Data MongoDB to do best effort optimisations required for sharded scenarios when using repositories. -This means essentially adding required shard key information, if not already present, to `replaceOne` filter queries when upserting entities. This may require an additional server round trip to determine the actual value of the current shard key. +Adding the `@Sharded` annotation to an entity enables Spring Data MongoDB to apply best effort optimisations required for sharded scenarios. +This means essentially adding required shard key information, if not already present, to `replaceOne` filter queries when upserting entities. +This may require an additional server round trip to determine the actual value of the current shard key. -TIP: By setting `@Sharded(immutableKey = true)` no attempt will be made to check if an entities shard key changed. +TIP: By setting `@Sharded(immutableKey = true)` Spring Data does not attempt to check if an entity shard key was changed. -Please see the https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#upsert[MongoDB Documentation] for further details and the list below for which operations are eligible for auto include the shard key. +Please see the https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#upsert[MongoDB Documentation] for further details. +The following list contains which operations are eligible for shard key auto-inclusion: -* `Reactive/CrudRepository.save(...)` -* `Reactive/CrudRepository.saveAll(...)` -* `Reactive/MongoTemplate.save(...)` +* `(Reactive)CrudRepository.save(…)` +* `(Reactive)CrudRepository.saveAll(…)` +* `(Reactive)MongoTemplate.save(…)` From 81c68955fed429123d01e9c4986b0b990e520b23 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 18 Feb 2020 15:12:15 +0100 Subject: [PATCH 0085/1381] DATAMONGO-2476 - Fix Json parsing for unquoted placeholders in arrays. Original pull request: #835. --- .../data/mongodb/util/json/JsonScanner.java | 2 +- .../ParameterBindingJsonReaderUnitTests.java | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java index a967cd8853..683da25753 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java @@ -219,7 +219,7 @@ private JsonToken scanBindString() { boolean isExpression = false; int parenthesisCount = 0; - while (c == '$' || c == '_' || Character.isLetterOrDigit(c) || c == '#' || c == '{' || c == '[' || c == ']' + while (c == '$' || c == '_' || Character.isLetterOrDigit(c) || c == '#' || c == '{' || c == '[' || (isExpression && isExpressionAllowedChar(c))) { if (charCount == 0 && c == '#') { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 876280e276..7754c083b5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -220,6 +220,41 @@ public TypedValue getRootObject() { assertThat(target).isEqualTo(new Document("name", "value")); } + @Test // DATAMONGO-2476 + public void bindUnquotedParameterInArray() { + + Document target = parse("{ 'name' : { $in : [?0] } }", "kohlin"); + assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("kohlin")))); + } + + @Test // DATAMONGO-2476 + public void bindMultipleUnquotedParameterInArray() { + + Document target = parse("{ 'name' : { $in : [?0,?1] } }", "dalinar", "kohlin"); + assertThat(target).isEqualTo(new Document("name", new Document("$in",Arrays.asList("dalinar", "kohlin")))); + } + + @Test // DATAMONGO-2476 + public void bindUnquotedParameterInArrayWithSpaces() { + + Document target = parse("{ 'name' : { $in : [ ?0 ] } }", "kohlin"); + assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("kohlin")))); + } + + @Test // DATAMONGO-2476 + public void bindQuotedParameterInArray() { + + Document target = parse("{ 'name' : { $in : ['?0'] } }", "kohlin"); + assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("kohlin")))); + } + + @Test // DATAMONGO-2476 + public void bindQuotedMulitParameterInArray() { + + Document target = parse("{ 'name' : { $in : ['?0,?1'] } }", "dalinar", "kohlin"); + assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("dalinar,kohlin")))); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); From c25a1a9e53f419eb7520d39b2c41de423627488c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 24 Feb 2020 11:22:41 +0100 Subject: [PATCH 0086/1381] DATAMONGO-2476 - Polishing. Convert test to JUnit 5. Original pull request: #835. --- .../ParameterBindingJsonReaderUnitTests.java | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 7754c083b5..b1ebc295d8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -25,7 +25,7 @@ import org.bson.Document; import org.bson.codecs.DecoderContext; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.expression.EvaluationContext; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -36,52 +36,52 @@ * * @author Christoph Strobl */ -public class ParameterBindingJsonReaderUnitTests { +class ParameterBindingJsonReaderUnitTests { @Test - public void bindUnquotedStringValue() { + void bindUnquotedStringValue() { Document target = parse("{ 'lastname' : ?0 }", "kohlin"); assertThat(target).isEqualTo(new Document("lastname", "kohlin")); } @Test - public void bindQuotedStringValue() { + void bindQuotedStringValue() { Document target = parse("{ 'lastname' : '?0' }", "kohlin"); assertThat(target).isEqualTo(new Document("lastname", "kohlin")); } @Test - public void bindUnquotedIntegerValue() { + void bindUnquotedIntegerValue() { Document target = parse("{ 'lastname' : ?0 } ", 100); assertThat(target).isEqualTo(new Document("lastname", 100)); } @Test - public void bindMultiplePlacholders() { + void bindMultiplePlacholders() { Document target = parse("{ 'lastname' : ?0, 'firstname' : '?1' }", "Kohlin", "Dalinar"); assertThat(target).isEqualTo(Document.parse("{ 'lastname' : 'Kohlin', 'firstname' : 'Dalinar' }")); } @Test - public void bindQuotedIntegerValue() { + void bindQuotedIntegerValue() { Document target = parse("{ 'lastname' : '?0' }", 100); assertThat(target).isEqualTo(new Document("lastname", "100")); } @Test - public void bindValueToRegex() { + void bindValueToRegex() { Document target = parse("{ 'lastname' : { '$regex' : '^(?0)'} }", "kohlin"); assertThat(target).isEqualTo(Document.parse("{ 'lastname' : { '$regex' : '^(kohlin)'} }")); } @Test - public void bindValueToMultiRegex() { + void bindValueToMultiRegex() { Document target = parse( "{'$or' : [{'firstname': {'$regex': '.*?0.*', '$options': 'i'}}, {'lastname' : {'$regex': '.*?0xyz.*', '$options': 'i'}} ]}", @@ -91,7 +91,7 @@ public void bindValueToMultiRegex() { } @Test - public void bindMultipleValuesToSingleToken() { + void bindMultipleValuesToSingleToken() { Document target = parse("{$where: 'return this.date.getUTCMonth() == ?2 && this.date.getUTCDay() == ?3;'}", 0, 1, 2, 3, 4); @@ -100,21 +100,21 @@ public void bindMultipleValuesToSingleToken() { } @Test - public void bindValueToDbRef() { + void bindValueToDbRef() { Document target = parse("{ 'reference' : { $ref : 'reference', $id : ?0 }}", "kohlin"); assertThat(target).isEqualTo(Document.parse("{ 'reference' : { $ref : 'reference', $id : 'kohlin' }}")); } @Test - public void bindToKey() { + void bindToKey() { Document target = parse("{ ?0 : ?1 }", "firstname", "kaladin"); assertThat(target).isEqualTo(Document.parse("{ 'firstname' : 'kaladin' }")); } @Test - public void bindListValue() { + void bindListValue() { // Document target = parse("{ 'lastname' : { $in : ?0 } }", Arrays.asList("Kohlin", "Davar")); @@ -122,7 +122,7 @@ public void bindListValue() { } @Test - public void bindListOfBinaryValue() { + void bindListOfBinaryValue() { // byte[] value = "Kohlin".getBytes(StandardCharsets.UTF_8); @@ -133,7 +133,7 @@ public void bindListOfBinaryValue() { } @Test - public void bindExtendedExpression() { + void bindExtendedExpression() { Document target = parse("{'id':?#{ [0] ? { $exists :true} : [1] }}", true, "firstname", "kaladin"); assertThat(target).isEqualTo(Document.parse("{ \"id\" : { \"$exists\" : true}}")); @@ -142,7 +142,7 @@ public void bindExtendedExpression() { // {'id':?#{ [0] ? { $exists :true} : [1] }} @Test - public void bindDocumentValue() { + void bindDocumentValue() { // Document target = parse("{ 'lastname' : ?0 }", new Document("$eq", "Kohlin")); @@ -150,7 +150,7 @@ public void bindDocumentValue() { } @Test - public void arrayWithoutBinding() { + void arrayWithoutBinding() { // Document target = parse("{ 'lastname' : { $in : [\"Kohlin\", \"Davar\"] } }"); @@ -158,7 +158,7 @@ public void arrayWithoutBinding() { } @Test - public void bindSpEL() { + void bindSpEL() { // "{ arg0 : ?#{[0]} }" Document target = parse("{ arg0 : ?#{[0]} }", 100.01D); @@ -166,7 +166,7 @@ public void bindSpEL() { } @Test // DATAMONGO-2315 - public void bindDateAsDate() { + void bindDateAsDate() { Date date = new Date(); Document target = parse("{ 'end_date' : { $gte : { $date : ?0 } } }", date); @@ -175,7 +175,7 @@ public void bindDateAsDate() { } @Test // DATAMONGO-2315 - public void bindQuotedDateAsDate() { + void bindQuotedDateAsDate() { Date date = new Date(); Document target = parse("{ 'end_date' : { $gte : { $date : '?0' } } }", date); @@ -184,7 +184,7 @@ public void bindQuotedDateAsDate() { } @Test // DATAMONGO-2315 - public void bindStringAsDate() { + void bindStringAsDate() { Date date = new Date(); Document target = parse("{ 'end_date' : { $gte : { $date : ?0 } } }", "2019-07-04T12:19:23.000Z"); @@ -193,7 +193,7 @@ public void bindStringAsDate() { } @Test // DATAMONGO-2315 - public void bindNumberAsDate() { + void bindNumberAsDate() { Long time = new Date().getTime(); Document target = parse("{ 'end_date' : { $gte : { $date : ?0 } } }", time); @@ -202,7 +202,7 @@ public void bindNumberAsDate() { } @Test // DATAMONGO-2418 - public void shouldNotAccessSpElEvaluationContextWhenNoSpElPresentInBindableTarget() { + void shouldNotAccessSpElEvaluationContextWhenNoSpElPresentInBindableTarget() { Object[] args = new Object[] { "value" }; EvaluationContext evaluationContext = new StandardEvaluationContext() { @@ -221,38 +221,39 @@ public TypedValue getRootObject() { } @Test // DATAMONGO-2476 - public void bindUnquotedParameterInArray() { + void bindUnquotedParameterInArray() { Document target = parse("{ 'name' : { $in : [?0] } }", "kohlin"); assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("kohlin")))); } @Test // DATAMONGO-2476 - public void bindMultipleUnquotedParameterInArray() { + void bindMultipleUnquotedParameterInArray() { Document target = parse("{ 'name' : { $in : [?0,?1] } }", "dalinar", "kohlin"); - assertThat(target).isEqualTo(new Document("name", new Document("$in",Arrays.asList("dalinar", "kohlin")))); + assertThat(target).isEqualTo(new Document("name", new Document("$in", Arrays.asList("dalinar", "kohlin")))); } @Test // DATAMONGO-2476 - public void bindUnquotedParameterInArrayWithSpaces() { + void bindUnquotedParameterInArrayWithSpaces() { Document target = parse("{ 'name' : { $in : [ ?0 ] } }", "kohlin"); assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("kohlin")))); } @Test // DATAMONGO-2476 - public void bindQuotedParameterInArray() { + void bindQuotedParameterInArray() { Document target = parse("{ 'name' : { $in : ['?0'] } }", "kohlin"); assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("kohlin")))); } @Test // DATAMONGO-2476 - public void bindQuotedMulitParameterInArray() { + void bindQuotedMulitParameterInArray() { Document target = parse("{ 'name' : { $in : ['?0,?1'] } }", "dalinar", "kohlin"); - assertThat(target).isEqualTo(new Document("name", new Document("$in", Collections.singletonList("dalinar,kohlin")))); + assertThat(target) + .isEqualTo(new Document("name", new Document("$in", Collections.singletonList("dalinar,kohlin")))); } private static Document parse(String json, Object... args) { From c4dcc7d0f59c506d3f439be2a481b16fea17c8e9 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 19 Feb 2020 10:46:16 +0100 Subject: [PATCH 0087/1381] DATAMONGO-2478 - Fix NPE in Query.of when given a proxied source. Original pull request: #836. --- .../data/mongodb/core/query/Query.java | 12 +++++------- .../data/mongodb/core/query/QueryTests.java | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 8 deletions(-) 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 6172a41986..32a08431dc 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 @@ -517,13 +517,11 @@ public boolean isSorted() { } }; - target.criteria.putAll(source.criteria); - target.skip = source.skip; - target.limit = source.limit; - target.sort = Sort.unsorted().and(source.sort); - target.hint = source.hint; - target.collation = source.collation; - target.restrictedTypes.addAll(source.restrictedTypes); + target.skip = source.getSkip(); + target.limit = source.getLimit(); + target.hint = source.getHint(); + target.collation = source.getCollation(); + target.restrictedTypes.addAll(source.getRestrictedTypes()); if (source.getMeta().hasValues()) { target.setMeta(new Meta(source.getMeta())); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java index b894ee9b2d..bfe80bde0e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java @@ -21,7 +21,7 @@ import org.bson.Document; import org.junit.Test; - +import org.springframework.aop.framework.ProxyFactory; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; @@ -337,6 +337,19 @@ public void clonedQueryShouldApplyRestrictionsFromBasicQuery() { .isNotEqualTo(source.getQueryObject()); } + @Test // DATAMONGO-2478 + public void queryOfShouldWorkOnProxiedObjects() { + + BasicQuery source = new BasicQuery("{ 'foo' : 'bar'}", "{ '_id' : -1, 'foo' : 1 }"); + source.withHint("the hint"); + source.limit(10); + source.setSortObject(new Document("_id", 1)); + + Query target = Query.of((Query) new ProxyFactory(source).getProxy()); + + compareQueries(target, source); + } + private void compareQueries(Query actual, Query expected) { assertThat(actual.getCollation()).isEqualTo(expected.getCollation()); From a6a84421b43ba5c0a4448271c072f680fb6b461d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 24 Feb 2020 11:34:26 +0100 Subject: [PATCH 0088/1381] DATAMONGO-2478 - Polishing. Convert test to JUnit 5. Original pull request: #836. --- .../data/mongodb/core/query/QueryTests.java | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java index bfe80bde0e..6e4b920860 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java @@ -20,7 +20,7 @@ import static org.springframework.data.mongodb.core.query.Query.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.aop.framework.ProxyFactory; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -38,17 +38,17 @@ * @author Christoph Strobl * @author Mark Paluch */ -public class QueryTests { +class QueryTests { @Test - public void testSimpleQuery() { + void testSimpleQuery() { Query q = new Query(where("name").is("Thomas").and("age").lt(80)); assertThat(q.getQueryObject()).isEqualTo(Document.parse("{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}")); } @Test - public void testQueryWithNot() { + void testQueryWithNot() { Query q = new Query(where("name").is("Thomas").and("age").not().mod(10, 0)); assertThat(q.getQueryObject()) @@ -56,14 +56,14 @@ public void testQueryWithNot() { } @Test - public void testInvalidQueryWithNotIs() { + void testInvalidQueryWithNotIs() { assertThatExceptionOfType(InvalidMongoDbApiUsageException.class) .isThrownBy(() -> new Query(where("name").not().is("Thomas"))); } @Test - public void testOrQuery() { + void testOrQuery() { Query q = new Query(new Criteria().orOperator(where("name").is("Sven").and("age").lt(50), where("age").lt(50), where("name").is("Thomas"))); @@ -72,7 +72,7 @@ public void testOrQuery() { } @Test - public void testAndQuery() { + void testAndQuery() { Query q = new Query(new Criteria().andOperator(where("name").is("Sven"), where("age").lt(50))); Document expected = Document.parse("{ \"$and\" : [ { \"name\" : \"Sven\"} , { \"age\" : { \"$lt\" : 50}}]}"); @@ -80,7 +80,7 @@ public void testAndQuery() { } @Test - public void testNorQuery() { + void testNorQuery() { Query q = new Query( new Criteria().norOperator(where("name").is("Sven"), where("age").lt(50), where("name").is("Thomas"))); @@ -89,7 +89,7 @@ public void testNorQuery() { } @Test - public void testQueryWithLimit() { + void testQueryWithLimit() { Query q = new Query(where("name").gte("M").lte("T").and("age").not().gt(22)); q.limit(50); @@ -100,7 +100,7 @@ public void testQueryWithLimit() { } @Test - public void testQueryWithFieldsAndSlice() { + void testQueryWithFieldsAndSlice() { Query q = new Query(where("name").gte("M").lte("T").and("age").not().gt(22)); q.fields().exclude("address").include("name").slice("orders", 10); @@ -113,7 +113,7 @@ public void testQueryWithFieldsAndSlice() { } @Test // DATAMONGO-652 - public void testQueryWithFieldsElemMatchAndPositionalOperator() { + void testQueryWithFieldsElemMatchAndPositionalOperator() { Query query = query(where("name").gte("M").lte("T").and("age").not().gt(22)); query.fields().elemMatch("products", where("name").is("milk")).position("comments", 2); @@ -125,14 +125,14 @@ public void testQueryWithFieldsElemMatchAndPositionalOperator() { } @Test - public void testSimpleQueryWithChainedCriteria() { + void testSimpleQueryWithChainedCriteria() { Query q = new Query(where("name").is("Thomas").and("age").lt(80)); assertThat(q.getQueryObject()).isEqualTo(Document.parse("{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}")); } @Test - public void testComplexQueryWithMultipleChainedCriteria() { + void testComplexQueryWithMultipleChainedCriteria() { Query q = new Query( where("name").regex("^T.*").and("age").gt(20).lt(80).and("city").in("Stockholm", "London", "New York")); @@ -143,22 +143,22 @@ public void testComplexQueryWithMultipleChainedCriteria() { } @Test - public void testAddCriteriaWithComplexQueryWithMultipleChainedCriteria() { + void testAddCriteriaWithComplexQueryWithMultipleChainedCriteria() { Query q1 = new Query( where("name").regex("^T.*").and("age").gt(20).lt(80).and("city").in("Stockholm", "London", "New York")); Query q2 = new Query(where("name").regex("^T.*").and("age").gt(20).lt(80)) .addCriteria(where("city").in("Stockholm", "London", "New York")); - assertThat(q1.getQueryObject().toString()).isEqualTo(q2.getQueryObject().toString()); + assertThat(q1.getQueryObject()).hasToString(q2.getQueryObject().toString()); Query q3 = new Query(where("name").regex("^T.*")).addCriteria(where("age").gt(20).lt(80)) .addCriteria(where("city").in("Stockholm", "London", "New York")); - assertThat(q1.getQueryObject().toString()).isEqualTo(q3.getQueryObject().toString()); + assertThat(q1.getQueryObject()).hasToString(q3.getQueryObject().toString()); } @Test - public void testQueryWithElemMatch() { + void testQueryWithElemMatch() { Query q = new Query(where("openingHours").elemMatch(where("dayOfWeek").is("Monday").and("open").lte("1800"))); assertThat(q.getQueryObject()).isEqualTo(Document.parse( @@ -166,14 +166,14 @@ public void testQueryWithElemMatch() { } @Test - public void testQueryWithIn() { + void testQueryWithIn() { Query q = new Query(where("state").in("NY", "NJ", "PA")); assertThat(q.getQueryObject()).isEqualTo(Document.parse("{ \"state\" : { \"$in\" : [ \"NY\" , \"NJ\" , \"PA\"]}}")); } @Test - public void testQueryWithRegex() { + void testQueryWithRegex() { Query q = new Query(where("name").regex("b.*")); assertThat(q.getQueryObject().toJson()) @@ -181,28 +181,28 @@ public void testQueryWithRegex() { } @Test - public void testQueryWithRegexAndOption() { + void testQueryWithRegexAndOption() { Query q = new Query(where("name").regex("b.*", "i")); assertThat(q.getQueryObject().toJson()) .isEqualTo(Document.parse("{ \"name\" : { \"$regex\" : \"b.*\" , \"$options\" : \"i\"}}").toJson()); } @Test // DATAMONGO-538 - public void addsSortCorrectly() { + void addsSortCorrectly() { Query query = new Query().with(Sort.by(Direction.DESC, "foo")); assertThat(query.getSortObject()).isEqualTo(Document.parse("{ \"foo\" : -1}")); } @Test - public void rejectsOrderWithIgnoreCase() { + void rejectsOrderWithIgnoreCase() { assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> new Query().with(Sort.by(Order.asc("foo").ignoreCase()))); } @Test // DATAMONGO-709, DATAMONGO-1735, // DATAMONGO-2198 - public void shouldReturnClassHierarchyOfRestrictedTypes() { + void shouldReturnClassHierarchyOfRestrictedTypes() { Query query = new Query(where("name").is("foo")).restrict(SpecialDoc.class); @@ -210,7 +210,7 @@ public void shouldReturnClassHierarchyOfRestrictedTypes() { } @Test // DATAMONGO-1421 - public void addCriteriaForSamePropertyMultipleTimesShouldThrowAndSafelySerializeErrorMessage() { + void addCriteriaForSamePropertyMultipleTimesShouldThrowAndSafelySerializeErrorMessage() { assertThatExceptionOfType(InvalidMongoDbApiUsageException.class).isThrownBy(() -> { @@ -222,7 +222,7 @@ public void addCriteriaForSamePropertyMultipleTimesShouldThrowAndSafelySerialize } @Test // DATAMONGO-1783 - public void queryOfShouldCreateNewQueryWithEqualBehaviour() { + void queryOfShouldCreateNewQueryWithEqualBehaviour() { Query source = new Query(); source.addCriteria(where("This you must ken!").is(EnumType.VAL_1)); @@ -231,7 +231,7 @@ public void queryOfShouldCreateNewQueryWithEqualBehaviour() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldNotDependOnCriteriaFromSource() { + void clonedQueryShouldNotDependOnCriteriaFromSource() { Query source = new Query(); source.addCriteria(where("From one make ten").is("and two let be.")); @@ -245,7 +245,7 @@ public void clonedQueryShouldNotDependOnCriteriaFromSource() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldAppendCriteria() { + void clonedQueryShouldAppendCriteria() { Query source = new Query(); source.addCriteria(where("Skip o'er the four!").is("From five and six")); @@ -259,7 +259,7 @@ public void clonedQueryShouldAppendCriteria() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldNotDependOnCollationFromSource() { + void clonedQueryShouldNotDependOnCollationFromSource() { Query source = new Query().collation(Collation.simple()); Query target = Query.of(source); @@ -271,7 +271,7 @@ public void clonedQueryShouldNotDependOnCollationFromSource() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldNotDependOnSortFromSource() { + void clonedQueryShouldNotDependOnSortFromSource() { Query source = new Query().with(Sort.by("And nine is one")); Query target = Query.of(source); @@ -284,7 +284,7 @@ public void clonedQueryShouldNotDependOnSortFromSource() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldNotDependOnFieldsFromSource() { + void clonedQueryShouldNotDependOnFieldsFromSource() { Query source = new Query(); source.fields().include("That is the witch's one-time-one!"); @@ -298,7 +298,7 @@ public void clonedQueryShouldNotDependOnFieldsFromSource() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldNotDependOnMetaFromSource() { + void clonedQueryShouldNotDependOnMetaFromSource() { Query source = new Query().maxTimeMsec(100); Query target = Query.of(source); @@ -312,7 +312,7 @@ public void clonedQueryShouldNotDependOnMetaFromSource() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldNotDependOnRestrictedTypesFromSource() { + void clonedQueryShouldNotDependOnRestrictedTypesFromSource() { Query source = new Query(); source.restrict(EnumType.class); @@ -325,7 +325,7 @@ public void clonedQueryShouldNotDependOnRestrictedTypesFromSource() { } @Test // DATAMONGO-1783 - public void clonedQueryShouldApplyRestrictionsFromBasicQuery() { + void clonedQueryShouldApplyRestrictionsFromBasicQuery() { BasicQuery source = new BasicQuery("{ 'foo' : 'bar'}"); Query target = Query.of(source); @@ -338,7 +338,7 @@ public void clonedQueryShouldApplyRestrictionsFromBasicQuery() { } @Test // DATAMONGO-2478 - public void queryOfShouldWorkOnProxiedObjects() { + void queryOfShouldWorkOnProxiedObjects() { BasicQuery source = new BasicQuery("{ 'foo' : 'bar'}", "{ '_id' : -1, 'foo' : 1 }"); source.withHint("the hint"); From fb45b4eb2a9bab5cb7ab7517f038d227c78f0646 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 26 Feb 2020 11:11:23 +0100 Subject: [PATCH 0089/1381] DATAMONGO-2452 - Updated changelog. --- src/main/resources/changelog.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 3eef84baef..81e59df2a8 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,15 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.16.RELEASE (2020-02-26) +---------------------------------------------- +* DATAMONGO-2464 - Fix code examples in reference documentation. +* DATAMONGO-2459 - Update Documentation of Reactive Repositories to mention usage of PageRequest. +* DATAMONGO-2457 - Reference documentation: Text does not match with code example. +* DATAMONGO-2452 - Release 2.1.16 (Lovelace SR16). +* DATAMONGO-2079 - MappingMongoConverter cannot be proxied because it implements the package-private ValueResolver interface. + + Changes in version 3.0.0.M3 (2020-02-12) ---------------------------------------- * DATAMONGO-2470 - Adapt tests to AssertJ 3.15.0. @@ -2911,3 +2920,4 @@ Repository + From 7849b5333b25ee1fcd7b8748ffeda41f829dc1e4 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 26 Feb 2020 11:37:53 +0100 Subject: [PATCH 0090/1381] DATAMONGO-2453 - Updated changelog. --- src/main/resources/changelog.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 81e59df2a8..4fe69366c9 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,19 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.5.RELEASE (2020-02-26) +--------------------------------------------- +* DATAMONGO-2478 - NPE when using Query annotation and with sort and pageable. +* DATAMONGO-2476 - JsonParseException: JSON reader was expecting a value but found '}'. +* DATAMONGO-2464 - Fix code examples in reference documentation. +* DATAMONGO-2460 - @Field annotation behaviour changed. +* DATAMONGO-2459 - Update Documentation of Reactive Repositories to mention usage of PageRequest. +* DATAMONGO-2457 - Reference documentation: Text does not match with code example. +* DATAMONGO-2453 - Release 2.2.5 (Moore SR5). +* DATAMONGO-2406 - Allow Mono as return type for derived deleteBy queries. +* DATAMONGO-2079 - MappingMongoConverter cannot be proxied because it implements the package-private ValueResolver interface. + + Changes in version 2.1.16.RELEASE (2020-02-26) ---------------------------------------------- * DATAMONGO-2464 - Fix code examples in reference documentation. @@ -2921,3 +2934,4 @@ Repository + From 96ffb0b7f44721803f9fc2666c3fe6ab60695c15 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 6 Mar 2020 09:20:55 +0100 Subject: [PATCH 0091/1381] DATAMONGO-2489 - Upgrade to MongoDB 4.0 Drivers. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8059c54cff..9d4d60f25a 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 4.0.0-rc0 + 4.0.0 ${mongo} 1.19 From 8029acb3fb800ee91efe8c62c422b99bff4086ec Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 27 Feb 2020 13:19:58 +0100 Subject: [PATCH 0092/1381] DATAMONGO-2481 - Improve build time. Introduce Junit Jupiter extensions. Flush collections instead of dropping them. Apply cursor timeout to change stream and capped collections in tests. Original pull request: #838. --- .../core/messaging/ChangeStreamRequest.java | 43 ++- .../core/messaging/ChangeStreamTask.java | 5 + .../core/messaging/SubscriptionRequest.java | 12 + .../core/messaging/TailableCursorTask.java | 6 + .../java/ConfigClassInDefaultPackage.java | 8 + .../ReactiveTransactionIntegrationTests.java | 7 + .../config/AbstractIntegrationTests.java | 8 + .../AbstractMongoConfigurationUnitTests.java | 1 + ...uditingViaJavaConfigRepositoriesTests.java | 19 +- .../mongodb/config/ReactiveAuditingTests.java | 14 +- .../ServerAddressPropertyEditorUnitTests.java | 13 +- ...DefaultBulkOperationsIntegrationTests.java | 26 +- ...efaultIndexOperationsIntegrationTests.java | 71 ++--- .../DefaultReactiveIndexOperationsTests.java | 76 +---- .../ExecutableFindOperationSupportTests.java | 19 +- ...ExecutableRemoveOperationSupportTests.java | 16 +- ...ExecutableUpdateOperationSupportTests.java | 17 +- .../mongodb/core/JsonSchemaQueryTests.java | 15 +- .../core/MongoTemplateCollationTests.java | 7 + .../mongodb/core/MongoTemplateDbRefTests.java | 35 +-- .../data/mongodb/core/MongoTemplateTests.java | 170 ++++------- .../core/MongoTemplateTransactionTests.java | 7 + .../core/MongoTemplateUpdateTests.java | 26 +- .../core/MongoTemplateValidationTests.java | 7 + .../data/mongodb/core/NoExplicitIdTests.java | 11 +- .../mongodb/core/QueryByExampleTests.java | 16 +- .../ReactiveMongoTemplateCollationTests.java | 7 + .../core/ReactiveMongoTemplateTests.java | 120 ++++---- .../mongodb/core/TestMongoConfiguration.java | 7 + .../core/aggregation/AggregationTests.java | 83 ++--- .../auditing/MongoTemplateAuditingTests.java | 9 + .../ReactiveMongoTemplateAuditingTests.java | 7 + .../convert/MappingMongoConverterTests.java | 14 +- .../MappingMongoConverterUnitTests.java | 1 - .../MongoConvertersIntegrationTests.java | 23 +- .../core/geo/AbstractGeoSpatialTests.java | 14 +- .../data/mongodb/core/geo/GeoJsonTests.java | 69 ++++- .../core/index/IndexingIntegrationTests.java | 7 + .../mongodb/core/index/TextIndexTests.java | 29 +- .../core/mapping/GeoIndexedAppConfig.java | 8 + .../mongodb/core/mapping/MappingTests.java | 41 ++- .../mongodb/core/mapreduce/GroupByTests.java | 37 +-- .../core/messaging/ChangeStreamTests.java | 62 ++-- .../DefaultMessageListenerContainerTests.java | 75 +++-- .../core/messaging/TailableCursorTests.java | 6 +- .../mongodb/core/query/CriteriaTests.java | 41 +-- .../mongodb/core/query/TextQueryTests.java | 22 +- .../core/schema/MongoJsonSchemaTests.java | 2 + .../schema/ReactiveMongoJsonSchemaTests.java | 7 + .../monitor/MongoMonitorIntegrationTests.java | 15 +- .../ComplexIdRepositoryIntegrationTests.java | 9 +- ...oRepositoryTextSearchIntegrationTests.java | 56 +--- .../PersonRepositoryTransactionalTests.java | 11 +- ...RepositoriesRegistrarIntegrationTests.java | 4 +- ...ComposedRepositoryImplementationTests.java | 4 +- ...ReactiveRepositoryImplementationTests.java | 4 +- .../CustomRepositoryImplementationTests.java | 4 +- ...veQuerydslMongoPredicateExecutorTests.java | 7 + .../support/SimpleMongoRepositoryTests.java | 45 ++- ...leMongoRepositoryVersionedEntityTests.java | 10 + ...veMongoRepositoryVersionedEntityTests.java | 8 + .../test/util/MongoClientExtension.java | 37 ++- .../mongodb/test/util/MongoExtensions.java | 41 +++ .../test/util/MongoTemplateExtension.java | 147 +++++++++ .../mongodb/test/util/MongoTestTemplate.java | 144 +++++++++ .../util/MongoTestTemplateConfiguration.java | 285 ++++++++++++++++++ .../mongodb/test/util/MongoTestUtils.java | 13 +- .../test/util/ReactiveMongoTestTemplate.java | 145 +++++++++ .../data/mongodb/test/util/Template.java | 56 ++++ 69 files changed, 1659 insertions(+), 732 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java index 71053ff0a2..c4ed0687cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.messaging; +import java.time.Duration; import java.time.Instant; import org.bson.BsonValue; @@ -167,21 +168,37 @@ public static class ChangeStreamRequestOptions implements SubscriptionRequest.Re private final @Nullable String databaseName; private final @Nullable String collectionName; + private final @Nullable Duration maxAwaitTime; private final ChangeStreamOptions options; /** * Create new {@link ChangeStreamRequestOptions}. * + * @param databaseName can be {@literal null}. * @param collectionName can be {@literal null}. * @param options must not be {@literal null}. */ public ChangeStreamRequestOptions(@Nullable String databaseName, @Nullable String collectionName, ChangeStreamOptions options) { + this(databaseName, collectionName, null, options); + } + + /** + * Create new {@link ChangeStreamRequestOptions}. + * + * @param databaseName can be {@literal null}. + * @param collectionName can be {@literal null}. + * @param maxAwaitTime can be {@literal null}. + * @param options must not be {@literal null}. + */ + public ChangeStreamRequestOptions(@Nullable String databaseName, @Nullable String collectionName, + @Nullable Duration maxAwaitTime, ChangeStreamOptions options) { Assert.notNull(options, "Options must not be null!"); this.collectionName = collectionName; this.databaseName = databaseName; + this.maxAwaitTime = maxAwaitTime; this.options = options; } @@ -219,6 +236,15 @@ public String getCollectionName() { public String getDatabaseName() { return databaseName; } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.monitor.SubscriptionRequest.RequestOptions#maxAwaitTime() + */ + @Override + public Duration maxAwaitTime() { + return maxAwaitTime != null ? maxAwaitTime : RequestOptions.super.maxAwaitTime(); + } } /** @@ -232,6 +258,7 @@ public static class ChangeStreamRequestBuilder { private @Nullable String databaseName; private @Nullable String collectionName; + private @Nullable Duration maxAwaitTime; private @Nullable MessageListener, ? super T> listener; private ChangeStreamOptionsBuilder delegate = ChangeStreamOptions.builder(); @@ -417,6 +444,20 @@ public ChangeStreamRequestBuilder fullDocumentLookup(FullDocument lookup) { return this; } + /** + * Set the cursors maximum wait time on the server (for a new Document to be emitted). + * + * @param timeout must not be {@literal null}. + * @since 3.0 + */ + public ChangeStreamRequestBuilder maxAwaitTime(Duration timeout) { + + Assert.notNull(timeout, "timeout not be null!"); + + this.maxAwaitTime = timeout; + return this; + } + /** * @return the build {@link ChangeStreamRequest}. */ @@ -425,7 +466,7 @@ public ChangeStreamRequest build() { Assert.notNull(listener, "MessageListener must not be null!"); return new ChangeStreamRequest<>(listener, - new ChangeStreamRequestOptions(databaseName, collectionName, delegate.build())); + new ChangeStreamRequestOptions(databaseName, collectionName, maxAwaitTime, delegate.build())); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java index 2e11b86ec6..81b67c2109 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; import org.bson.BsonDocument; import org.bson.BsonTimestamp; @@ -135,6 +136,10 @@ protected MongoCursor> initCursor(MongoTemplate t iterable = filter.isEmpty() ? db.watch(Document.class) : db.watch(filter, Document.class); } + if (!options.maxAwaitTime().isZero()) { + iterable = iterable.maxAwaitTime(options.maxAwaitTime().toMillis(), TimeUnit.MILLISECONDS); + } + if (!resumeToken.isEmpty()) { if (resumeAfter) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index 7a7b2d64d3..a6d1d28d23 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.messaging; +import java.time.Duration; + import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.lang.Nullable; @@ -72,6 +74,16 @@ default String getDatabaseName() { @Nullable String getCollectionName(); + /** + * Get the maximum wait time (the time till the next Document is emitted) to apply when reading from the collection. + * + * @return never {@literal null}. {@link Duration#ZERO} by default. + * @since 3.0 + */ + default Duration maxAwaitTime() { + return Duration.ZERO; + } + /** * Create empty options. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java index 9425a64a7b..f4e0c2145a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.messaging; +import java.util.concurrent.TimeUnit; + import org.bson.Document; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -75,6 +77,10 @@ protected MongoCursor initCursor(MongoTemplate template, RequestOption iterable = iterable.collation(collation); } + if (!options.maxAwaitTime().isZero()) { + iterable = iterable.maxAwaitTime(options.maxAwaitTime().toMillis(), TimeUnit.MILLISECONDS); + } + return iterable.iterator(); } } diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java index 8e11758747..7316f4c2de 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java @@ -15,6 +15,9 @@ * limitations under the License. */ +import java.util.Collections; +import java.util.Set; + import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; @@ -46,4 +49,9 @@ protected String getDatabaseName() { public MongoClient mongoClient() { return MongoClients.create(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index 61f9bdf9f0..7127c85639 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -23,6 +23,8 @@ import reactor.test.StepVerifier; import java.time.Duration; +import java.util.Collections; +import java.util.Set; import org.bson.types.ObjectId; import org.junit.jupiter.api.AfterAll; @@ -238,6 +240,11 @@ protected String getDatabaseName() { public ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory factory) { return new ReactiveMongoTransactionManager(factory); } + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(Person.class); + } } @RequiredArgsConstructor diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 345551a195..29b24dd5c0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -17,6 +17,9 @@ import static org.springframework.data.mongodb.test.util.Assertions.*; +import java.util.Collections; +import java.util.Set; + import org.bson.Document; import org.junit.After; import org.junit.Before; @@ -54,6 +57,11 @@ protected String getDatabaseName() { public MongoClient mongoClient() { return MongoTestUtils.client(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoOperations operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index c811bba4b8..50debf50b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -172,6 +172,7 @@ public MappingMongoConverter mappingMongoConverter() throws Exception { public MongoTypeMapper typeMapper() { return new CustomMongoTypeMapper(); } + } static class ConfigurationWithMultipleBasePackages extends AbstractMongoClientConfiguration { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java index 53d42af97c..27e3b05b71 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java @@ -18,8 +18,11 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import org.junit.jupiter.api.BeforeEach; @@ -28,7 +31,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Version; import org.springframework.data.domain.AuditorAware; import org.springframework.data.mongodb.core.AuditablePerson; @@ -68,7 +73,8 @@ public class AuditingViaJavaConfigRepositoriesTests { @Configuration @EnableMongoAuditing(auditorAwareRef = "auditorProvider") - @EnableMongoRepositories(basePackageClasses = AuditablePersonRepository.class, considerNestedRepositories = true) + @EnableMongoRepositories(basePackageClasses = AuditablePersonRepository.class, considerNestedRepositories = true, + includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AuditablePersonRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Override @@ -86,6 +92,12 @@ public MongoClient mongoClient() { public AuditorAware auditorProvider() { return mock(AuditorAware.class); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>( + Arrays.asList(AuditablePerson.class, VersionedAuditablePerson.class, SimpleVersionedAuditablePerson.class)); + } } @BeforeEach @@ -212,6 +224,11 @@ public MongoClient mongoClient() { protected String getDatabaseName() { return "database"; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } static class VersionedAuditablePerson extends AuditablePerson { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index 3c1d29c536..f79b88e456 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -21,7 +21,10 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -29,7 +32,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Version; import org.springframework.data.domain.AuditorAware; import org.springframework.data.mongodb.core.AuditablePerson; @@ -63,7 +68,8 @@ public class ReactiveAuditingTests { @Configuration @EnableMongoAuditing(auditorAwareRef = "auditorProvider") - @EnableReactiveMongoRepositories(basePackageClasses = ReactiveAuditingTests.class, considerNestedRepositories = true) + @EnableReactiveMongoRepositories(basePackageClasses = ReactiveAuditingTests.class, considerNestedRepositories = true, + includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ReactiveAuditablePersonRepository.class)) static class Config extends AbstractReactiveMongoConfiguration { @Override @@ -76,6 +82,12 @@ public MongoClient reactiveMongoClient() { return mongoClient; } + @Override + protected Set> getInitialEntitySet() { + return new HashSet<>( + Arrays.asList(AuditablePerson.class, VersionedAuditablePerson.class, SimpleVersionedAuditablePerson.class)); + } + @Bean @SuppressWarnings("unchecked") public AuditorAware auditorProvider() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java index d07ef99225..854501f600 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java @@ -23,8 +23,9 @@ import java.util.Arrays; import java.util.Collection; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; import com.mongodb.ServerAddress; @@ -38,12 +39,12 @@ public class ServerAddressPropertyEditorUnitTests { ServerAddressPropertyEditor editor; - @Before + @BeforeEach public void setUp() { editor = new ServerAddressPropertyEditor(); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-454, DATAMONGO-1062 + @Test // DATAMONGO-454, DATAMONGO-1062 public void rejectsAddressConfigWithoutASingleParsableAndResolvableServerAddress() { String unknownHost1 = "gugu.nonexistant.example.org"; @@ -51,10 +52,12 @@ public void rejectsAddressConfigWithoutASingleParsableAndResolvableServerAddress assertUnresolveableHostnames(unknownHost1, unknownHost2); - editor.setAsText(unknownHost1 + "," + unknownHost2); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> editor.setAsText(unknownHost1 + "," + unknownHost2)); } @Test // DATAMONGO-454 + @EnabledIfSystemProperty(named = "user.name", matches = "jenkins") public void skipsUnparsableAddressIfAtLeastOneIsParsable() throws UnknownHostException { editor.setAsText("foo, localhost"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java index 982c2374af..3a04a67a0a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java @@ -23,10 +23,9 @@ import java.util.Optional; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.dao.DuplicateKeyException; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; @@ -36,9 +35,10 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.data.util.Pair; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoBulkWriteException; import com.mongodb.WriteConcern; @@ -52,21 +52,17 @@ * @author Christoph Strobl * @author Minsu Kim */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class DefaultBulkOperationsIntegrationTests { static final String COLLECTION_NAME = "bulk_ops"; - @Autowired MongoOperations operations; + @Template(initialEntitySet = BaseDoc.class) // + static MongoTestTemplate operations; - MongoCollection collection; - - @Before + @BeforeEach public void setUp() { - - this.collection = this.operations.getCollection(COLLECTION_NAME); - this.collection.deleteMany(new Document()); + operations.flush(COLLECTION_NAME); } @Test // DATAMONGO-934 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java index 9876ba493d..638a8546f5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java @@ -16,27 +16,26 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.Assumptions.*; import static org.springframework.data.mongodb.core.index.PartialIndexFilter.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import org.bson.BsonDocument; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.IndexDefinition; import org.springframework.data.mongodb.core.index.IndexInfo; +import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation.CaseFirst; -import org.springframework.data.util.Version; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ObjectUtils; import com.mongodb.client.MongoCollection; @@ -49,43 +48,27 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class DefaultIndexOperationsIntegrationTests { - private static final Version THREE_DOT_TWO = new Version(3, 2); - private static final Version THREE_DOT_FOUR = new Version(3, 4); - private static Version mongoVersion; + static final String COLLECTION_NAME = "default-index-operations-tests"; static final org.bson.Document GEO_SPHERE_2D = new org.bson.Document("loaction", "2dsphere"); - @Autowired MongoTemplate template; - DefaultIndexOperations indexOps; - MongoCollection collection; + @Template // + static MongoTestTemplate template; - @Before - public void setUp() { - - queryMongoVersionIfNecessary(); - String collectionName = this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - - this.collection = this.template.getDb().getCollection(collectionName, Document.class); - this.collection.dropIndexes(); - this.indexOps = new DefaultIndexOperations(template.getMongoDbFactory(), collectionName, - new QueryMapper(template.getConverter())); - } + MongoCollection collection = template.getCollection(COLLECTION_NAME); + IndexOperations indexOps = template.indexOps(COLLECTION_NAME); - private void queryMongoVersionIfNecessary() { - - if (mongoVersion == null) { - Document result = template.executeCommand("{ buildInfo: 1 }"); - mongoVersion = Version.parse(result.get("version").toString()); - } + @BeforeEach + public void setUp() { + template.dropIndexes(COLLECTION_NAME); } @Test // DATAMONGO-1008 public void getIndexInfoShouldBeAbleToRead2dsphereIndex() { - collection.createIndex(GEO_SPHERE_2D); + template.getCollection(COLLECTION_NAME).createIndex(GEO_SPHERE_2D); IndexInfo info = findAndReturnIndexInfo(GEO_SPHERE_2D); assertThat(info.getIndexFields().get(0).isGeo()).isEqualTo(true); @@ -94,8 +77,6 @@ public void getIndexInfoShouldBeAbleToRead2dsphereIndex() { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldApplyPartialFilterCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-criteria").on("k3y", Direction.ASC) .partial(of(where("q-t-y").gte(10))); @@ -109,12 +90,10 @@ public void shouldApplyPartialFilterCorrectly() { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-mapped-criteria").on("k3y", Direction.ASC) .partial(of(where("quantity").gte(10))); - indexOps.ensureIndex(id); + template.indexOps(DefaultIndexOperationsIntegrationTestsSample.class).ensureIndex(id); IndexInfo info = findAndReturnIndexInfo(indexOps.getIndexInfo(), "partial-with-mapped-criteria"); assertThat(Document.parse(info.getPartialFilterExpression())) @@ -124,8 +103,6 @@ public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldApplyPartialDBOFilterCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-dbo").on("k3y", Direction.ASC) .partial(of(new org.bson.Document("qty", new org.bson.Document("$gte", 10)))); @@ -139,13 +116,10 @@ public void shouldApplyPartialDBOFilterCorrectly() { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldFavorExplicitMappingHintViaClass() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-inheritance").on("k3y", Direction.ASC) .partial(of(where("age").gte(10))); - indexOps = new DefaultIndexOperations(template.getMongoDbFactory(), - this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class), + indexOps = new DefaultIndexOperations(template.getMongoDbFactory(), COLLECTION_NAME, new QueryMapper(template.getConverter()), MappingToSameCollection.class); indexOps.ensureIndex(id); @@ -173,14 +147,11 @@ public void shouldReadIndexWithPartialFilterContainingDbRefCorrectly() { @Test // DATAMONGO-1518 public void shouldCreateIndexWithCollationCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_FOUR)).isTrue(); - IndexDefinition id = new Index().named("with-collation").on("xyz", Direction.ASC) .collation(Collation.of("de_AT").caseFirst(CaseFirst.off())); - new DefaultIndexOperations(template.getMongoDbFactory(), - this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class), - new QueryMapper(template.getConverter()), MappingToSameCollection.class); + new DefaultIndexOperations(template.getMongoDbFactory(), COLLECTION_NAME, new QueryMapper(template.getConverter()), + MappingToSameCollection.class); indexOps.ensureIndex(id); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index 1f4dd31fa9..4fe2888be7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; -import static org.junit.Assume.*; import static org.springframework.data.mongodb.core.index.PartialIndexFilter.*; import static org.springframework.data.mongodb.core.query.Criteria.*; @@ -25,14 +24,10 @@ import java.util.function.Predicate; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.IndexDefinition; @@ -40,71 +35,36 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation.CaseFirst; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.util.Version; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.ReactiveMongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoCollection; /** * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith(MongoTemplateExtension.class) public class DefaultReactiveIndexOperationsTests { - @Configuration - static class Config extends AbstractReactiveMongoConfiguration { - - @Override - public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); - } - - @Override - protected String getDatabaseName() { - return "index-ops-tests"; - } - } - - private static final Version THREE_DOT_TWO = new Version(3, 2); - private static final Version THREE_DOT_FOUR = new Version(3, 4); - private static Version mongoVersion; + @Template(initialEntitySet = DefaultIndexOperationsIntegrationTestsSample.class) + static ReactiveMongoTestTemplate template; - @Autowired ReactiveMongoTemplate template; + String collectionName = template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - MongoCollection collection; - DefaultReactiveIndexOperations indexOps; + MongoCollection collection = template.getCollection(collectionName); + DefaultReactiveIndexOperations indexOps = new DefaultReactiveIndexOperations(template, collectionName, + new QueryMapper(template.getConverter())); - @Before + @BeforeEach public void setUp() { - - queryMongoVersionIfNecessary(); - String collectionName = this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - - this.collection = this.template.getMongoDatabase().getCollection(collectionName, Document.class); - this.indexOps = new DefaultReactiveIndexOperations(template, collectionName, - new QueryMapper(template.getConverter())); - StepVerifier.create(this.collection.dropIndexes()).verifyComplete(); } - private void queryMongoVersionIfNecessary() { - - if (mongoVersion == null) { - Document result = template.executeCommand("{ buildInfo: 1 }").block(); - mongoVersion = Version.parse(result.get("version").toString()); - } - } - @Test // DATAMONGO-1518 public void shouldCreateIndexWithCollationCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_FOUR)); - IndexDefinition id = new Index().named("with-collation").on("xyz", Direction.ASC) .collation(Collation.of("de_AT").caseFirst(CaseFirst.off())); @@ -137,8 +97,6 @@ public void shouldCreateIndexWithCollationCorrectly() { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldApplyPartialFilterCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-criteria").on("k3y", Direction.ASC) .partial(of(where("q-t-y").gte(10))); @@ -155,8 +113,6 @@ public void shouldApplyPartialFilterCorrectly() { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-mapped-criteria").on("k3y", Direction.ASC) .partial(of(where("quantity").gte(10))); @@ -172,8 +128,6 @@ public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldApplyPartialDBOFilterCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-dbo").on("k3y", Direction.ASC) .partial(of(new org.bson.Document("qty", new org.bson.Document("$gte", 10)))); @@ -191,8 +145,6 @@ public void shouldApplyPartialDBOFilterCorrectly() { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldFavorExplicitMappingHintViaClass() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-inheritance").on("k3y", Direction.ASC) .partial(of(where("age").gte(10))); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java index 58c91e88d5..0a0e3e04f3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java @@ -44,10 +44,9 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.NearQuery; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; - -import com.mongodb.client.MongoClient; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * Integration tests for {@link ExecutableFindOperationSupport}. @@ -55,13 +54,14 @@ * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class ExecutableFindOperationSupportTests { private static final String STAR_WARS = "star-wars"; private static final String STAR_WARS_PLANETS = "star-wars-universe"; - static @Client MongoClient mongoClient; - MongoTemplate template; + + @Template(database = "executable-find-operation-support-tests", initialEntitySet = { Person.class, Planet.class }) // + static MongoTestTemplate template; Person han; Person luke; @@ -72,10 +72,7 @@ public class ExecutableFindOperationSupportTests { @BeforeEach public void setUp() { - template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableFindOperationSupportTests")); - template.dropCollection(STAR_WARS); - template.dropCollection(STAR_WARS_PLANETS); + template.flush(); template.indexOps(Planet.class).ensureIndex( new GeospatialIndex("coordinates").typed(GeoSpatialIndexType.GEO_2DSPHERE).named("planet-coordinate-idx")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java index bbf9cabe01..cec119d49c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java @@ -28,10 +28,10 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.result.DeleteResult; /** @@ -40,13 +40,13 @@ * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class ExecutableRemoveOperationSupportTests { private static final String STAR_WARS = "star-wars"; - static @Client MongoClient mongoClient; - MongoTemplate template; + @Template(initialEntitySet = Person.class) // + static MongoTestTemplate template; Person han; Person luke; @@ -54,9 +54,7 @@ public class ExecutableRemoveOperationSupportTests { @BeforeEach public void setUp() { - template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableRemoveOperationSupportTests")); - template.dropCollection(STAR_WARS); + template.flush(); han = new Person(); han.firstname = "han"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java index 73a52737a6..712c5ce027 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java @@ -31,10 +31,10 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.result.UpdateResult; /** @@ -43,12 +43,13 @@ * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class ExecutableUpdateOperationSupportTests { private static final String STAR_WARS = "star-wars"; - static @Client MongoClient mongoClient; - MongoTemplate template; + + @Template(initialEntitySet = { Human.class, Jedi.class, Person.class }) // + static MongoTestTemplate template; Person han; Person luke; @@ -56,9 +57,7 @@ public class ExecutableUpdateOperationSupportTests { @BeforeEach public void setUp() { - template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableUpdateOperationSupportTests")); - template.dropCollection(STAR_WARS); + template.flush(); han = new Person(); han.firstname = "han"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java index 6ad794e763..62b8efd40a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java @@ -31,29 +31,30 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; - -import com.mongodb.client.MongoClient; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class JsonSchemaQueryTests { public static final String DATABASE_NAME = "json-schema-query-tests"; - static @Client MongoClient client; static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient; - MongoTemplate template; + @Template(database = DATABASE_NAME, initialEntitySet = Person.class) // + static MongoTestTemplate template; + Person jellyBelly, roseSpringHeart, kazmardBoombub; @BeforeEach public void setUp() { - template = new MongoTemplate(client, DATABASE_NAME); + template.flush(); jellyBelly = new Person(); jellyBelly.id = "1"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java index ed0607f4fb..95844332a6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java @@ -17,8 +17,10 @@ import static org.assertj.core.api.Assertions.*; +import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -63,6 +65,11 @@ protected String getDatabaseName() { protected boolean autoIndexCreation() { return false; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java index 5f779f322c..74a0641305 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java @@ -35,10 +35,10 @@ import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoId; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.model.Filters; /** @@ -47,31 +47,24 @@ * * @author Christoph Strobl */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class MongoTemplateDbRefTests { - static @Client MongoClient mongoClient; + @Template(database = "mongo-template-dbref-tests", + initialEntitySet = { RefCycleLoadingIntoDifferentTypeRoot.class, + RefCycleLoadingIntoDifferentTypeIntermediate.class, RefCycleLoadingIntoDifferentTypeRootView.class, + WithDBRefOnRawStringId.class, WithLazyDBRefOnRawStringId.class, WithRefToAnotherDb.class, + WithLazyRefToAnotherDb.class, WithListRefToAnotherDb.class, WithLazyListRefToAnotherDb.class }) // + static MongoTestTemplate template; - MongoTemplate template; - MongoTemplate otherDbTemplate; + @Template(database = "mongo-template-dbref-tests-other-db", initialEntitySet = JustSomeType.class) // + static MongoTestTemplate otherDbTemplate; @BeforeEach public void setUp() { - template = new MongoTemplate(mongoClient, "mongo-template-dbref-tests"); - - template.dropCollection(RefCycleLoadingIntoDifferentTypeRoot.class); - template.dropCollection(RefCycleLoadingIntoDifferentTypeIntermediate.class); - template.dropCollection(RefCycleLoadingIntoDifferentTypeRootView.class); - template.dropCollection(WithDBRefOnRawStringId.class); - template.dropCollection(WithLazyDBRefOnRawStringId.class); - template.dropCollection(WithRefToAnotherDb.class); - template.dropCollection(WithLazyRefToAnotherDb.class); - template.dropCollection(WithListRefToAnotherDb.class); - template.dropCollection(WithLazyListRefToAnotherDb.class); - - otherDbTemplate = new MongoTemplate(mongoClient, "mongo-template-dbref-tests-other-db"); - otherDbTemplate.dropCollection(JustSomeType.class); + template.flush(); + otherDbTemplate.flush(); } @Test // DATAMONGO-1703 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 24e3feeaf8..af65ca01fb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -40,14 +40,11 @@ import org.bson.types.ObjectId; import org.joda.time.DateTime; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.convert.converter.Converter; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; @@ -64,13 +61,9 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mapping.MappingException; -import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.LazyLoadingProxy; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.index.Index; @@ -78,22 +71,20 @@ import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoId; -import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; -import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.CloseableIterator; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -128,111 +119,72 @@ * @author Laszlo Csontos * @author duozhilin */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoClientExtension.class) public class MongoTemplateTests { - @Autowired MongoTemplate template; - @Autowired MongoDatabaseFactory factory; + public static final String DB_NAME = "mongo-template-tests"; - ConfigurableApplicationContext context; - MongoTemplate mappingTemplate; + static @Client MongoClient client; - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); + ConfigurableApplicationContext context = new GenericApplicationContext(); - @Autowired - public void setApplicationContext(ConfigurableApplicationContext context) { + MongoTestTemplate template = new MongoTestTemplate(cfg -> { - this.context = context; + cfg.configureDatabaseFactory(it -> { - context.addApplicationListener(new PersonWithIdPropertyOfTypeUUIDListener()); + it.client(client); + it.defaultDb(DB_NAME); + }); - PersistentEntities entities = PersistentEntities.of(template.getConverter().getMappingContext()); + cfg.configureMappingContext(it -> { + it.autocreateIndex(false); + it.intitalEntitySet(AuditablePerson.class); - context.addApplicationListener(new AuditingEventListener(() -> new IsNewAwareAuditingHandler(entities))); - } + }); - @Autowired - public void setMongoClient(MongoClient mongo) throws Exception { + cfg.configureApplicationContext(it -> { + it.applicationContext(context); + it.addEventListener(new PersonWithIdPropertyOfTypeUUIDListener()); + }); - CustomConversions conversions = new MongoCustomConversions( - Arrays.asList(DateToDateTimeConverter.INSTANCE, DateTimeToDateConverter.INSTANCE)); + cfg.configureAuditing(it -> { + it.auditingHandler(IsNewAwareAuditingHandler::new); + }); + }); - MongoMappingContext mappingContext = new MongoMappingContext(); - mappingContext.setInitialEntitySet( - new HashSet<>(Arrays.asList(PersonWith_idPropertyOfTypeObjectId.class, PersonWith_idPropertyOfTypeString.class, - PersonWithIdPropertyOfTypeObjectId.class, PersonWithIdPropertyOfTypeString.class, - PersonWithIdPropertyOfTypeInteger.class, PersonWithIdPropertyOfTypeBigInteger.class, - PersonWithIdPropertyOfPrimitiveInt.class, PersonWithIdPropertyOfTypeLong.class, - PersonWithIdPropertyOfPrimitiveLong.class, PersonWithIdPropertyOfTypeUUID.class))); - mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); - mappingContext.initialize(); + MongoTestTemplate mappingTemplate = new MongoTestTemplate(cfg -> { - DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); - MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mappingContext); - mappingConverter.setCustomConversions(conversions); - mappingConverter.afterPropertiesSet(); + cfg.configureDatabaseFactory(it -> { - this.mappingTemplate = new MongoTemplate(factory, mappingConverter); - } + it.client(client); + it.defaultDb(DB_NAME); + }); - @Before - public void setUp() { + cfg.configureConversion(it -> { + it.customConverters(DateToDateTimeConverter.INSTANCE, DateTimeToDateConverter.INSTANCE); + }); - cleanDb(); + cfg.configureMappingContext(it -> { + it.autocreateIndex(false); + }); - this.mappingTemplate.setApplicationContext(context); - } + cfg.configureApplicationContext(it -> { + it.applicationContext(new GenericApplicationContext()); + it.addEventListener(new PersonWithIdPropertyOfTypeUUIDListener()); + }); + }); - @After + MongoDatabaseFactory factory = template.getMongoDbFactory(); + + @AfterEach public void cleanUp() { - cleanDb(); - } - protected void cleanDb() { + template.flush(); + template.flush("collection", "personX", "findandreplace"); + + mappingTemplate.flush(); + template.dropCollection(Person.class); - template.dropCollection(PersonWithAList.class); - template.dropCollection(PersonWith_idPropertyOfTypeObjectId.class); - template.dropCollection(PersonWith_idPropertyOfTypeString.class); - template.dropCollection(PersonWithIdPropertyOfTypeObjectId.class); - template.dropCollection(PersonWithIdPropertyOfTypeString.class); - template.dropCollection(PersonWithIdPropertyOfTypeInteger.class); - template.dropCollection(PersonWithIdPropertyOfTypeBigInteger.class); - template.dropCollection(PersonWithIdPropertyOfPrimitiveInt.class); - template.dropCollection(PersonWithIdPropertyOfTypeLong.class); - template.dropCollection(PersonWithIdPropertyOfPrimitiveLong.class); - template.dropCollection(PersonWithIdPropertyOfTypeUUID.class); - template.dropCollection(PersonWithVersionPropertyOfTypeInteger.class); - template.dropCollection(TestClass.class); - template.dropCollection(Sample.class); - template.dropCollection(MyPerson.class); - template.dropCollection(TypeWithFieldAnnotation.class); - template.dropCollection(TypeWithDate.class); - template.dropCollection("collection"); - template.dropCollection("personX"); - template.dropCollection("findandreplace"); - template.dropCollection(Document.class); - template.dropCollection(ObjectWith3AliasedFields.class); - template.dropCollection(ObjectWith3AliasedFieldsAndNestedAddress.class); - template.dropCollection(BaseDoc.class); - template.dropCollection(ObjectWithEnumValue.class); - template.dropCollection(DocumentWithCollection.class); - template.dropCollection(DocumentWithCollectionOfSimpleType.class); - template.dropCollection(DocumentWithMultipleCollections.class); - template.dropCollection(DocumentWithNestedCollection.class); - template.dropCollection(DocumentWithEmbeddedDocumentWithCollection.class); - template.dropCollection(DocumentWithNestedList.class); - template.dropCollection(DocumentWithDBRefCollection.class); - template.dropCollection(SomeContent.class); - template.dropCollection(SomeTemplate.class); - template.dropCollection(Address.class); - template.dropCollection(DocumentWithCollectionOfSamples.class); - template.dropCollection(WithGeoJson.class); - template.dropCollection(DocumentWithNestedTypeHavingStringIdProperty.class); - template.dropCollection(ImmutableAudited.class); - template.dropCollection(RawStringId.class); - template.dropCollection(Outer.class); - template.dropCollection(Message.class); } @Test @@ -408,7 +360,7 @@ public void testEnsureIndex() throws Exception { @Test // DATAMONGO-746, DATAMONGO-2264 public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() throws Exception { - template.indexOps(Person.class).dropAllIndexes(); + template.dropCollection(Person.class); assertThat(template.indexOps(Person.class).getIndexInfo().isEmpty()).isTrue(); @@ -1314,6 +1266,7 @@ class ClassWithDBRefs { @Test // DATADOC-202 public void executeDocument() { + template.insert(new Person("Tom")); template.insert(new Person("Dick")); template.insert(new Person("Harry")); @@ -1487,7 +1440,7 @@ public void exceutesBasicQueryCorrectly() { assertThat(result.get(0).getName()).isEqualTo("Oleg"); } - @Test(expected = OptimisticLockingFailureException.class) // DATAMONGO-279 + @Test // DATAMONGO-279 public void optimisticLockingHandling() { // Init version @@ -1519,7 +1472,9 @@ public void optimisticLockingHandling() { person.version = 0; person.firstName = "Patryk3"; - template.save(person); + final PersonWithVersionPropertyOfTypeInteger toBeSaved = person; + + assertThatExceptionOfType(OptimisticLockingFailureException.class).isThrownBy(() -> template.save(toBeSaved)); } @Test // DATAMONGO-562 @@ -1595,13 +1550,14 @@ public void savesPlainDocumentCorrectly() { assertThat(document.containsKey("_id")).isTrue(); } - @Test(expected = MappingException.class) // DATAMONGO-550, DATAMONGO-1730 + @Test // DATAMONGO-550, DATAMONGO-1730 public void rejectsPlainObjectWithOutExplicitCollection() { org.bson.Document document = new org.bson.Document("foo", "bar"); template.save(document, "collection"); - template.findById(document.get("_id"), org.bson.Document.class); + assertThatExceptionOfType(MappingException.class) + .isThrownBy(() -> template.findById(document.get("_id"), org.bson.Document.class)); } @Test // DATAMONGO-550 @@ -1709,7 +1665,7 @@ public void correctlySetsLongVersionProperty() { assertThat(person.version).isEqualTo(0L); } - @Test(expected = DuplicateKeyException.class) // DATAMONGO-622 + @Test // DATAMONGO-622 public void preventsDuplicateInsert() { template.setWriteConcern(WriteConcern.ACKNOWLEDGED); @@ -1721,7 +1677,7 @@ public void preventsDuplicateInsert() { assertThat(person.version).isEqualTo(0); person.version = null; - template.save(person); + assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(() -> template.save(person)); } @Test // DATAMONGO-629 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index 0c2ae519b1..f612bd4575 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -23,7 +23,9 @@ import lombok.AllArgsConstructor; import lombok.Data; +import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.bson.Document; @@ -93,6 +95,11 @@ protected boolean autoIndexCreation() { MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index bb777b2c1a..1f85b8ee21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -27,7 +27,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Version; import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; @@ -39,34 +38,25 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; -import org.springframework.data.mongodb.test.util.MongoClientExtension; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; /** * @author Christoph Strobl */ -@ExtendWith({ MongoClientExtension.class }) +@ExtendWith({ MongoTemplateExtension.class }) class MongoTemplateUpdateTests { - static final String DB_NAME = "update-test"; - - static @Client MongoClient client; - - MongoTemplate template; + @Template(initialEntitySet = { Score.class, Versioned.class, Book.class }) // + static MongoTestTemplate template; @BeforeEach void setUp() { - - template = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, DB_NAME)); - - MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Score.class), client); - MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Versioned.class), client); - MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Book.class), client); + template.flush(); } @Test // DATAMONGO-2331 @@ -305,7 +295,7 @@ private List all(Class type) { } private MongoCollection collection(Class type) { - return client.getDatabase(DB_NAME).getCollection(template.getCollectionName(type)); + return template.getCollection(template.getCollectionName(type)); } @Document("scores") 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 index 4550b7d465..828573826e 100644 --- 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 @@ -22,7 +22,9 @@ import lombok.AllArgsConstructor; import lombok.Data; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -75,6 +77,11 @@ protected String getDatabaseName() { protected boolean autoIndexCreation() { return false; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java index d228f742d4..1f1979b2d4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java @@ -19,14 +19,18 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @@ -50,7 +54,7 @@ public class NoExplicitIdTests { static @Client MongoClient mongoClient; @Configuration - @EnableMongoRepositories(considerNestedRepositories = true) + @EnableMongoRepositories(considerNestedRepositories = true, includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TypeWithoutExplicitIdPropertyRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Override @@ -67,6 +71,11 @@ public MongoClient mongoClient() { protected boolean autoIndexCreation() { return false; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoOperations mongoOps; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java index 34e719dd1d..bd10c900bd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java @@ -33,10 +33,9 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UntypedExampleMatcher; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; - -import com.mongodb.client.MongoClient; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * Integration tests for Query-by-example. @@ -45,19 +44,18 @@ * @author Mark Paluch * @author Oliver Gierke */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class QueryByExampleTests { - static @Client MongoClient mongoClient; + @Template(initialEntitySet = Person.class) // + static MongoTestTemplate operations; - MongoOperations operations; Person p1, p2, p3; @BeforeEach public void setUp() { - operations = new MongoTemplate(mongoClient, "query-by-example"); - operations.remove(new Query(), Person.class); + operations.flush(); p1 = new Person(); p1.firstname = "bran"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java index 53f95e070b..c3541bc3ec 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java @@ -21,7 +21,9 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -61,6 +63,11 @@ public MongoClient reactiveMongoClient() { protected String getDatabaseName() { return "collation-tests"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.emptySet(); + } } @Autowired ReactiveMongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index 571f1d875e..0cd95d6a4e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -43,20 +43,16 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.assertj.core.api.Assumptions; import org.bson.BsonDocument; import org.bson.BsonTimestamp; import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -67,6 +63,7 @@ import org.springframework.data.domain.Sort.Direction; import org.springframework.data.geo.Metrics; import org.springframework.data.mapping.MappingException; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplateTests.Address; import org.springframework.data.mongodb.core.MongoTemplateTests.PersonWithConvertedId; import org.springframework.data.mongodb.core.MongoTemplateTests.VersionedPerson; @@ -80,14 +77,15 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.ReactiveMongoTestTemplate; import com.mongodb.WriteConcern; +import com.mongodb.reactivestreams.client.MongoClient; /** * Integration test for {@link MongoTemplate}. @@ -95,34 +93,37 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:reactive-infrastructure.xml") +@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) public class ReactiveMongoTemplateTests { - @Autowired SimpleReactiveMongoDatabaseFactory factory; - @Autowired ReactiveMongoTemplate template; - @Autowired ConfigurableApplicationContext context; - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); + public static final String DB_NAME = "reactive-mongo-template-tests"; + static @Client MongoClient client; - @Before + ConfigurableApplicationContext context = new GenericApplicationContext(); + ReactiveMongoTestTemplate template = new ReactiveMongoTestTemplate(cfg -> { + + cfg.configureDatabaseFactory(it -> { + + it.client(client); + it.defaultDb(DB_NAME); + }); + + cfg.configureApplicationContext(it -> { + it.applicationContext(context); + }); + }); + + ReactiveMongoDatabaseFactory factory = template.getDatabaseFactory(); + + @AfterEach public void setUp() { - Flux.merge(template.dropCollection("people"), // - template.dropCollection("personX"), // - template.dropCollection("collection"), // - template.dropCollection(Person.class), // - template.dropCollection(Venue.class), // - template.dropCollection(PersonWithAList.class), // - template.dropCollection(PersonWithIdPropertyOfTypeObjectId.class), // - template.dropCollection(PersonWithVersionPropertyOfTypeInteger.class), // - template.dropCollection(Sample.class), // - template.dropCollection(MyPerson.class)) // - .as(StepVerifier::create).verifyComplete(); + template.flush().as(StepVerifier::create).verifyComplete(); + template.flush("people", "collection").as(StepVerifier::create).verifyComplete(); + template.dropCollection(Person.class).as(StepVerifier::create).verifyComplete(); + template.dropCollection("personX").as(StepVerifier::create).verifyComplete(); } - @After - public void cleanUp() {} - @Test // DATAMONGO-1444 public void insertSetsId() { @@ -952,7 +953,7 @@ public void savesPlainDbObjectCorrectly() { assertThat(dbObject.containsKey("_id")).isTrue(); } - @Test(expected = MappingException.class) // DATAMONGO-1444, DATAMONGO-1730 + @Test // DATAMONGO-1444, DATAMONGO-1730 public void rejectsPlainObjectWithOutExplicitCollection() { Document dbObject = new Document("foo", "bar"); @@ -962,9 +963,8 @@ public void rejectsPlainObjectWithOutExplicitCollection() { .expectNextCount(1) // .verifyComplete(); - template.findById(dbObject.get("_id"), Document.class) // - .as(StepVerifier::create) // - .verifyError(MappingException.class); + assertThatExceptionOfType(MappingException.class) + .isThrownBy(() -> template.findById(dbObject.get("_id"), Document.class)); } @Test // DATAMONGO-1444 @@ -1363,11 +1363,10 @@ public void testDistinct() { } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeEmittedCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1396,11 +1395,10 @@ public void changeStreamEventsShouldBeEmittedCorrectly() throws InterruptedExcep } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1429,11 +1427,10 @@ public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedExc } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1463,10 +1460,9 @@ public void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedExce } @Test // DATAMONGO-1803 + @EnableIfReplicaSetAvailable public void mapsReservedWordsCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1506,11 +1502,10 @@ public void mapsReservedWordsCorrectly() throws InterruptedException { } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeResumedCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1586,7 +1581,6 @@ public void removeShouldConsiderSkipAndSort() { } @Test // DATAMONGO-2189 - @DirtiesContext public void afterSaveEventContainsSavedObjectUsingInsert() { AtomicReference saved = createAfterSaveReference(); @@ -1602,7 +1596,6 @@ public void afterSaveEventContainsSavedObjectUsingInsert() { } @Test // DATAMONGO-2189 - @DirtiesContext public void afterSaveEventContainsSavedObjectUsingInsertAll() { AtomicReference saved = createAfterSaveReference(); @@ -1618,11 +1611,10 @@ public void afterSaveEventContainsSavedObjectUsingInsertAll() { } @Test // DATAMONGO-2012 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") + @EnableIfReplicaSetAvailable public void watchesDatabaseCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); template.createCollection("personX").as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1660,11 +1652,10 @@ public void watchesDatabaseCorrectly() throws InterruptedException { } @Test // DATAMONGO-2012, DATAMONGO-2113 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") + @EnableIfReplicaSetAvailable public void resumesAtTimestampCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1711,11 +1702,10 @@ public void resumesAtTimestampCorrectly() throws InterruptedException { } @Test // DATAMONGO-2115 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") + @EnableIfReplicaSetAvailable public void resumesAtBsonTimestampCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java index 8d5017c7a3..9a9cd95e9a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java @@ -16,7 +16,9 @@ package org.springframework.data.mongodb.core; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.core.convert.converter.Converter; @@ -54,4 +56,9 @@ public CustomConversions customConversions() { converters.add(new org.springframework.data.mongodb.core.PersonWriteConverter()); return new MongoCustomConversions(converters); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index 06a068dc2b..33e9fdb342 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -38,15 +38,12 @@ import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; @@ -69,14 +66,16 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.Person; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.data.util.CloseableIterator; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.InsertOneModel; +import com.mongodb.client.model.WriteModel; /** * Tests for {@link MongoTemplate#aggregate(Aggregation, Class, Class)}. @@ -91,8 +90,7 @@ * @author Sergey Shcherbakov * @author Minsu Kim */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class AggregationTests { private static final String INPUT_COLLECTION = "aggregation_test_collection"; @@ -100,43 +98,29 @@ public class AggregationTests { private static boolean initialized = false; - @Autowired MongoTemplate mongoTemplate; - - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); + @Template // + static MongoTestTemplate mongoTemplate; - @Before + @BeforeEach public void setUp() { cleanDb(); initSampleDataIfNecessary(); } - @After + @AfterEach public void cleanUp() { cleanDb(); } private void cleanDb() { + mongoTemplate.flush(Product.class, UserWithLikes.class, DATAMONGO753.class, Data.class, DATAMONGO788.class, + User.class, Person.class, Reservation.class, Venue.class, MeterData.class, LineItem.class, InventoryItem.class, + Sales.class, Sales2.class, Employee.class, Art.class, Venue.class); + mongoTemplate.dropCollection(INPUT_COLLECTION); - mongoTemplate.dropCollection(Product.class); - mongoTemplate.dropCollection(UserWithLikes.class); - mongoTemplate.dropCollection(DATAMONGO753.class); - mongoTemplate.dropCollection(Data.class); - mongoTemplate.dropCollection(DATAMONGO788.class); - mongoTemplate.dropCollection(User.class); - mongoTemplate.dropCollection(Person.class); - mongoTemplate.dropCollection(Reservation.class); - mongoTemplate.dropCollection(Venue.class); - mongoTemplate.dropCollection(MeterData.class); - mongoTemplate.dropCollection(LineItem.class); - mongoTemplate.dropCollection(InventoryItem.class); - mongoTemplate.dropCollection(Sales.class); - mongoTemplate.dropCollection(Sales2.class); - mongoTemplate.dropCollection(Employee.class); - mongoTemplate.dropCollection(Art.class); mongoTemplate.dropCollection("personQueryTemp"); - mongoTemplate.dropCollection(Venue.class); } /** @@ -149,20 +133,19 @@ private void initSampleDataIfNecessary() { if (!initialized) { - LOGGER.debug("Server uses MongoDB Version: {}", mongoVersion); - mongoTemplate.dropCollection(ZipInfo.class); mongoTemplate.execute(ZipInfo.class, new CollectionCallback() { @Override public Void doInCollection(MongoCollection collection) throws MongoException, DataAccessException { + List> docs = new ArrayList<>(); Scanner scanner = null; try { scanner = new Scanner(new BufferedInputStream(new ClassPathResource("zips.json").getInputStream())); while (scanner.hasNextLine()) { String zipInfoRecord = scanner.nextLine(); - collection.insertOne(Document.parse(zipInfoRecord)); + docs.add(new InsertOneModel<>(Document.parse(zipInfoRecord))); } } catch (Exception e) { if (scanner != null) { @@ -171,6 +154,7 @@ public Void doInCollection(MongoCollection collection) throws MongoExc throw new RuntimeException("Could not load mongodb sample dataset!", e); } + collection.bulkWrite(docs); return null; } }); @@ -305,7 +289,6 @@ public void shouldAggregateEmptyCollectionAndStream() { } @Test // DATAMONGO-1391 - @MongoVersion(asOf = "3.2") public void shouldUnwindWithIndex() { MongoCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); @@ -332,7 +315,6 @@ public void shouldUnwindWithIndex() { } @Test // DATAMONGO-1391 - @MongoVersion(asOf = "3.2") public void shouldUnwindPreserveEmpty() { MongoCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); @@ -521,7 +503,7 @@ public void findStatesWithPopulationOver10MillionAggregationExample() { /* //complex mongodb aggregation framework example from https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state - + db.zipcodes.aggregate( { $group: { @@ -952,7 +934,6 @@ public void expressionsInProjectionExample() { } @Test // DATAMONGO-774 - @MongoVersion(asOf = "2.4") public void stringExpressionsInProjectionExample() { Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); @@ -1051,7 +1032,6 @@ public void aliasesNestedFieldInProjectionImmediately() { } @Test // DATAMONGO-774 - @MongoVersion(asOf = "2.4") public void shouldPerformDateProjectionOperatorsCorrectly() throws ParseException { Data data = new Data(); @@ -1078,7 +1058,6 @@ public void shouldPerformDateProjectionOperatorsCorrectly() throws ParseExceptio } @Test // DATAMONGO-774 - @MongoVersion(asOf = "2.4") public void shouldPerformStringProjectionOperatorsCorrectly() throws ParseException { Data data = new Data(); @@ -1115,7 +1094,6 @@ public void shouldPerformStringProjectionOperatorsCorrectly() throws ParseExcept } @Test // DATAMONGO-1550 - @MongoVersion(asOf = "3.4") public void shouldPerformReplaceRootOperatorCorrectly() throws ParseException { Data data = new Data(); @@ -1263,7 +1241,6 @@ public void shouldAllowGroupingByAliasedFieldDefinedInFormerAggregationStage() { } @Test // DATAMONGO-960 - @MongoVersion(asOf = "2.6") public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabled() { createUserWithLikesDocuments(); @@ -1287,7 +1264,6 @@ public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOp } @Test // DATAMONGO-1637 - @MongoVersion(asOf = "2.6") public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabledWhileStreaming() { createUserWithLikesDocuments(); @@ -1314,7 +1290,6 @@ public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOp } @Test // DATAMONGO-960 - @MongoVersion(asOf = "2.6") public void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithExplainOptionEnabled() { createUserWithLikesDocuments(); @@ -1333,7 +1308,6 @@ public void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithEx } @Test // DATAMONGO-954, DATAMONGO-2264 - @MongoVersion(asOf = "2.6") public void shouldSupportReturningCurrentAggregationRoot() { mongoTemplate.save(new Person("p1_first", "p1_last", 25)); @@ -1359,7 +1333,6 @@ public void shouldSupportReturningCurrentAggregationRoot() { * {@link https://stackoverflow.com/questions/24185987/using-root-inside-spring-data-mongodb-for-retrieving-whole-document} */ @Test // DATAMONGO-954, DATAMONGO-2264 - @MongoVersion(asOf = "2.6") public void shouldSupportReturningCurrentAggregationRootInReference() { mongoTemplate.save(new Reservation("0123", "42", 100)); @@ -1379,7 +1352,6 @@ public void shouldSupportReturningCurrentAggregationRootInReference() { } @Test // DATAMONGO-1549 - @MongoVersion(asOf = "3.4") public void shouldApplyCountCorrectly() { mongoTemplate.save(new Reservation("0123", "42", 100)); @@ -1537,7 +1509,6 @@ public void shouldHonorFieldAliasesForFieldReferences() { } @Test // DATAMONGO-1326 - @MongoVersion(asOf = "3.2") public void shouldLookupPeopleCorectly() { createUsersWithReferencedPersons(); @@ -1557,7 +1528,6 @@ public void shouldLookupPeopleCorectly() { } @Test // DATAMONGO-1326 - @MongoVersion(asOf = "3.2") public void shouldGroupByAndLookupPeopleCorectly() { createUsersWithReferencedPersons(); @@ -1603,7 +1573,6 @@ public void shouldCreateOutputCollection() { } @Test // DATAMONGO-1637 - @MongoVersion(asOf = "2.6") public void shouldCreateOutputCollectionWhileStreaming() { createPersonDocuments(); @@ -1626,7 +1595,6 @@ public void shouldCreateOutputCollectionWhileStreaming() { } @Test // DATAMONGO-1637 - @MongoVersion(asOf = "2.6") public void shouldReturnDocumentsWithOutputCollectionWhileStreaming() { createPersonDocuments(); @@ -1666,7 +1634,6 @@ public void outShouldOutBeTheLastOperation() { } @Test // DATAMONGO-1325 - @MongoVersion(asOf = "3.2") public void shouldApplySampleCorrectly() { createUserWithLikesDocuments(); @@ -1700,7 +1667,6 @@ public void sliceShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1491 - @MongoVersion(asOf = "3.2") public void filterShouldBeAppliedCorrectly() { Item item43 = Item.builder().itemId("43").quantity(2).price(2L).build(); @@ -1731,7 +1697,6 @@ public void filterShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1538 - @MongoVersion(asOf = "3.2") public void letShouldBeAppliedCorrectly() { Sales2 sales1 = Sales2.builder().id("1").price(10).tax(0.5F).applyDiscount(true).build(); @@ -1756,7 +1721,6 @@ public void letShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1551, DATAMONGO-2264 - @MongoVersion(asOf = "3.4") public void graphLookupShouldBeAppliedCorrectly() { Employee em1 = Employee.builder().id(1).name("Dev").build(); @@ -1789,7 +1753,6 @@ public void graphLookupShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1552 - @MongoVersion(asOf = "3.4") public void bucketShouldCollectDocumentsIntoABucket() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); @@ -1824,7 +1787,6 @@ public void bucketShouldCollectDocumentsIntoABucket() { } @Test // DATAMONGO-1552, DATAMONGO-2437 - @MongoVersion(asOf = "3.4") public void bucketAutoShouldCollectDocumentsIntoABucket() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); @@ -1858,7 +1820,6 @@ public void bucketAutoShouldCollectDocumentsIntoABucket() { } @Test // DATAMONGO-1552 - @MongoVersion(asOf = "3.4") public void facetShouldCreateFacets() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index b8d0ed1506..20289bfa21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -19,6 +19,10 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -61,6 +65,11 @@ public MongoClient mongoClient() { protected String getDatabaseName() { return "mongo-template-audit-tests"; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>(Arrays.asList(ImmutableAuditableEntityWithVersion.class, KAuditableVersionedEntity.class)); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 752c99cbfc..46b575f35f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -23,6 +23,8 @@ import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -71,6 +73,11 @@ public MongoClient reactiveMongoClient() { protected String getDatabaseName() { return DB_NAME; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.emptySet(); + } } @Autowired ReactiveMongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index dcad856382..aa4e485f0b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -31,6 +31,7 @@ import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import org.bson.Document; @@ -48,6 +49,7 @@ import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; /** * Integration tests for {@link MappingMongoConverter}. @@ -58,8 +60,11 @@ public class MappingMongoConverterTests { public static final String DATABASE = "mapping-converter-tests"; + static @Client MongoClient client; + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); + MappingMongoConverter converter; MongoMappingContext mappingContext; DbRefResolver dbRefResolver; @@ -67,12 +72,17 @@ public class MappingMongoConverterTests { @BeforeEach public void setUp() { - client.getDatabase(DATABASE).drop(); + MongoDatabase database = client.getDatabase(DATABASE); - MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); + database.getCollection("samples").deleteMany(new Document()); + database.getCollection("java-time-types").deleteMany(new Document()); dbRefResolver = spy(new DefaultDbRefResolver(factory)); + mappingContext = new MongoMappingContext(); + mappingContext.setInitialEntitySet(new HashSet<>( + Arrays.asList(WithLazyDBRefAsConstructorArg.class, WithLazyDBRef.class, WithJavaTimeTypes.class))); + mappingContext.setAutoIndexCreation(false); mappingContext.afterPropertiesSet(); converter = new MappingMongoConverter(dbRefResolver, mappingContext); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index c46f599f38..7722044bae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -41,7 +41,6 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; - import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.factory.annotation.Value; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java index 9f09d79be2..aa1258cc42 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java @@ -24,17 +24,16 @@ import java.util.UUID; import org.bson.types.Binary; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * Integration tests for {@link MongoConverters}. @@ -43,17 +42,17 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class MongoConvertersIntegrationTests { static final String COLLECTION = "converter-tests"; - @Autowired MongoOperations template; + @Template // + static MongoTestTemplate template; - @Before + @BeforeEach public void setUp() { - template.dropCollection(COLLECTION); + template.flush(COLLECTION); } @Test // DATAMONGO-422 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java index a03e406760..d2e856d33a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java @@ -19,7 +19,9 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.joda.time.LocalDate; import org.junit.After; @@ -35,9 +37,11 @@ import org.springframework.data.geo.Point; import org.springframework.data.geo.Polygon; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.TestEntities; import org.springframework.data.mongodb.core.Venue; +import org.springframework.data.mongodb.core.geo.GeoJsonTests.Venue2DSphere; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -67,6 +71,11 @@ protected String getDatabaseName() { public MongoClient mongoClient() { return MongoTestUtils.client(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; @@ -102,7 +111,10 @@ protected void removeVenues() { } protected void addVenues() { - template.insertAll(TestEntities.geolocation().newYork()); + + + template.bulkOps(BulkMode.UNORDERED, Venue.class).insert(TestEntities.geolocation().newYork()).execute(); +// template.insertAll(TestEntities.geolocation().newYork()); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index ed9d941672..ee41648495 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -21,15 +21,17 @@ import lombok.Data; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.assertj.core.data.Percentage; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; @@ -39,6 +41,7 @@ import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.CollectionCallback; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; @@ -54,7 +57,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.MongoException; -import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; @@ -80,6 +82,12 @@ protected String getDatabaseName() { public MongoClient mongoClient() { return mongoClient; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>(Arrays.asList(Venue2DSphere.class, VenueWithDistanceField.class, OpenGeoJson.class, + DocumentWithPropertyUsingGeoJsonType.class)); + } } @Autowired MongoTemplate template; @@ -87,7 +95,13 @@ public MongoClient mongoClient() { @BeforeEach public void setUp() { - template.setWriteConcern(WriteConcern.JOURNALED); + // template.setWriteConcern(WriteConcern.JOURNALED); + + // createIndex(); + // addVenues(); + } + + private void createIndexAndAddVenues() { createIndex(); addVenues(); @@ -103,6 +117,8 @@ public void tearDown() { @Test // DATAMONGO-1135, DATAMONGO-2264 public void geoNear() { + createIndexAndAddVenues(); + NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class); @@ -115,6 +131,8 @@ public void geoNear() { @Test // DATAMONGO-2264 public void geoNearShouldNotOverridePropertyWithDefaultNameForCalculatedDistance/* namely "dis" */() { + createIndexAndAddVenues(); + NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults result = template.geoNear(geoNear, VenueWithDistanceField.class); @@ -132,6 +150,8 @@ public void geoNear() { @Test // DATAMONGO-2264 public void geoNearShouldAllowToReadBackCalculatedDistanceIntoTargetTypeProperty/* namely "dis" */() { + createIndexAndAddVenues(); + NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class, @@ -150,6 +170,7 @@ public void geoNear() { @Test // DATAMONGO-1148 public void geoNearShouldReturnDistanceCorrectlyUsingGeoJson/*which is using the meters*/() { + createIndexAndAddVenues(); NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73.99171, 40.738868), Metrics.KILOMETERS).num(10) .maxDistance(0.4); @@ -165,6 +186,7 @@ public void geoNear() { @Test // DATAMONGO-1348 public void geoNearShouldReturnDistanceCorrectly/*which is using the meters*/() { + createIndexAndAddVenues(); NearQuery geoNear = NearQuery.near(new Point(-73.99171, 40.738868), Metrics.KILOMETERS).num(10).maxDistance(0.4); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class); @@ -179,6 +201,7 @@ public void geoNear() { @Test // DATAMONGO-1135 public void geoNearWithMiles() { + createIndexAndAddVenues(); NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.MILES).num(10).maxDistance(93.2057); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class); @@ -190,6 +213,8 @@ public void geoNearWithMiles() { @Test // DATAMONGO-1135 public void withinPolygon() { + createIndexAndAddVenues(); + Point first = new Point(-73.99756, 40.73083); Point second = new Point(-73.99756, 40.741404); Point third = new Point(-73.988135, 40.741404); @@ -204,6 +229,8 @@ public void withinPolygon() { @Test // DATAMONGO-1135 public void nearPoint() { + createIndexAndAddVenues(); + GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); Query query = query(where("location").near(point).maxDistance(0.01)); @@ -214,6 +241,8 @@ public void nearPoint() { @Test // DATAMONGO-1135 public void nearSphere() { + createIndexAndAddVenues(); + GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); Query query = query(where("location").nearSphere(point).maxDistance(0.003712240453784)); @@ -335,6 +364,8 @@ public void shouldSaveAndRetrieveDocumentWithGeoJsonGeometryCollectionTypeCorrec @Test // DATAMONGO-1110 public void nearWithMinDistance() { + createIndexAndAddVenues(); + Point point = new GeoJsonPoint(-73.99171, 40.738868); List venues = template.find(query(where("location").near(point).minDistance(0.01)), Venue2DSphere.class); @@ -345,6 +376,8 @@ public void nearWithMinDistance() { @Test // DATAMONGO-1110 public void nearSphereWithMinDistance() { + createIndexAndAddVenues(); + Point point = new GeoJsonPoint(-73.99171, 40.738868); List venues = template.find(query(where("location").nearSphere(point).minDistance(0.01)), Venue2DSphere.class); @@ -355,6 +388,8 @@ public void nearSphereWithMinDistance() { @Test // DATAMONGO-1135 public void nearWithMinAndMaxDistance() { + createIndexAndAddVenues(); + GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); Query query = query(where("location").near(point).minDistance(0.01).maxDistance(100)); @@ -444,18 +479,22 @@ public void readGeoJsonBasedOnEmbeddedTypeInformation() { private void addVenues() { - template.insert(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); - template.insert(new Venue2DSphere("10gen Office", -73.99171, 40.738868)); - template.insert(new Venue2DSphere("Flatiron Building", -73.988135, 40.741404)); - template.insert(new Venue2DSphere("Players Club", -73.997812, 40.739128)); - template.insert(new Venue2DSphere("City Bakery ", -73.992491, 40.738673)); - template.insert(new Venue2DSphere("Splash Bar", -73.992491, 40.738673)); - template.insert(new Venue2DSphere("Momofuku Milk Bar", -73.985839, 40.731698)); - template.insert(new Venue2DSphere("Shake Shack", -73.98820, 40.74164)); - template.insert(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); - template.insert(new Venue2DSphere("Empire State Building", -73.98602, 40.74894)); - template.insert(new Venue2DSphere("Ulaanbaatar, Mongolia", 106.9154, 47.9245)); - template.insert(new Venue2DSphere("Maplewood, NJ", -74.2713, 40.73137)); + List venues = new ArrayList<>(); + + venues.add(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); + venues.add(new Venue2DSphere("10gen Office", -73.99171, 40.738868)); + venues.add(new Venue2DSphere("Flatiron Building", -73.988135, 40.741404)); + venues.add(new Venue2DSphere("Players Club", -73.997812, 40.739128)); + venues.add(new Venue2DSphere("City Bakery ", -73.992491, 40.738673)); + venues.add(new Venue2DSphere("Splash Bar", -73.992491, 40.738673)); + venues.add(new Venue2DSphere("Momofuku Milk Bar", -73.985839, 40.731698)); + venues.add(new Venue2DSphere("Shake Shack", -73.98820, 40.74164)); + venues.add(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); + venues.add(new Venue2DSphere("Empire State Building", -73.98602, 40.74894)); + venues.add(new Venue2DSphere("Ulaanbaatar, Mongolia", 106.9154, 47.9245)); + venues.add(new Venue2DSphere("Maplewood, NJ", -74.2713, 40.73137)); + + template.bulkOps(BulkMode.UNORDERED, Venue2DSphere.class).insert(venues).execute(); } protected void createIndex() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 31dfbc0f0b..acfab7bfb8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -25,8 +25,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -88,6 +90,11 @@ protected String getDatabaseName() { TimeoutResolver myTimeoutResolver() { return new TimeoutResolver("11s"); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @AfterEach diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java index 8f15f45831..2512cfcfdc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java @@ -19,36 +19,37 @@ import java.util.List; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionOptions; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Language; import org.springframework.data.mongodb.core.query.Collation; - -import com.mongodb.WriteConcern; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * @author Christoph Strobl * @author Mark Paluch */ -public class TextIndexTests extends AbstractIntegrationTests { +@ExtendWith(MongoTemplateExtension.class) +public class TextIndexTests { + + @Template(initialEntitySet = TextIndexedDocumentRoot.class) + static MongoTestTemplate template; - private @Autowired MongoTemplate template; private IndexOperations indexOps; - @Before - public void setUp() throws Exception { + @BeforeEach + public void beforeEach() throws Exception { - template.setWriteConcern(WriteConcern.JOURNALED); this.indexOps = template.indexOps(TextIndexedDocumentRoot.class); - template.dropCollection(TextIndexedDocumentRoot.class); + template.dropDatabase(); + template.createCollection(TextIndexedDocumentRoot.class, CollectionOptions.empty().collation(Collation.of("de_AT"))); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java index 3aa11afd14..966f146846 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java @@ -15,6 +15,9 @@ */ package org.springframework.data.mongodb.core.mapping; +import java.util.Collections; +import java.util.Set; + import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.mapping.event.LoggingEventListener; @@ -47,4 +50,9 @@ public String getMappingBasePackage() { public LoggingEventListener mappingEventsListener() { return new LoggingEventListener(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java index ce991c6766..f6addcd40d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java @@ -29,22 +29,26 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Test; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.dao.DataAccessException; import org.springframework.dao.DuplicateKeyException; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.MongoCollectionUtils; -import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionCallback; -import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import com.mongodb.MongoException; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; /** @@ -53,9 +57,23 @@ * @author Thomas Darimont * @author Mark Paluch */ -public class MappingTests extends AbstractIntegrationTests { +@ExtendWith(MongoTemplateExtension.class) +public class MappingTests { + + static final String DB_NAME = "mapping-tests"; + + static @Client MongoClient client; - @Autowired MongoOperations template; + @Template(database = DB_NAME, + initialEntitySet = { PersonWithDbRef.class, GeoLocation.class, PersonPojoStringId.class, Account.class, + DetectedCollectionWithIndex.class, Item.class, Container.class, Person.class, PersonCustomCollection1.class, + GeneratedId.class, PersonWithObjectId.class, PersonCustomIdName.class, PersonMapProperty.class }) // + static MongoTestTemplate template; + + @AfterEach + void afterEach() { + template.flush(); + } @Test public void testGeneratedId() { @@ -164,10 +182,12 @@ public void testWriteEntity() { assertThat(result.get(0).getAccounts()).isNotNull(); } - @Test(expected = DuplicateKeyException.class) + @Test @SuppressWarnings({ "unchecked", "rawtypes" }) public void testUniqueIndex() { + MongoTemplate template = new MongoTemplate(client, DB_NAME); + Address addr = new Address(); addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" }); addr.setCity("Anytown"); @@ -177,7 +197,7 @@ public void testUniqueIndex() { Person p1 = new Person(1234567890, "John", "Doe", 37, addr); Person p2 = new Person(1234567890, "Jane", "Doe", 38, addr); - template.insertAll(Arrays.asList(p1, p2)); + assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(() -> template.insertAll(Arrays.asList(p1, p2))); } @Test @@ -206,6 +226,9 @@ public void testPrimitivesAndCustomCollectionName() { @Test public void testIndexesCreatedInRightCollection() { + + MongoTemplate template = new MongoTemplate(client, DB_NAME); + CustomCollectionWithIndex ccwi = new CustomCollectionWithIndex("test"); template.insert(ccwi); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java index f5bd71ded2..35cf09a0c9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java @@ -21,18 +21,15 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoCollection; @@ -43,24 +40,20 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ SpringExtension.class, MongoServerCondition.class }) +@EnableIfMongoServerVersion(isLessThan = "4.1") @ContextConfiguration("classpath:infrastructure.xml") public class GroupByTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_MOST_4_0 = MongoVersionRule.atMost(Version.parse("4.0.999")); + static final String GROUP_TEST_COLLECTION = "group_test_collection"; @Autowired MongoTemplate mongoTemplate; - @Before + @BeforeEach public void setUp() { cleanDb(); } - @After - public void cleanUp() { - cleanDb(); - } - protected void cleanDb() { mongoTemplate.dropCollection(mongoTemplate.getCollectionName(XObject.class)); mongoTemplate.dropCollection("group_test_collection"); @@ -96,7 +89,7 @@ public void keyFunctionCreation() { public void simpleGroupFunction() { createGroupByData(); - GroupByResults results = mongoTemplate.group("group_test_collection", GroupBy.key("x") + GroupByResults results = mongoTemplate.group(GROUP_TEST_COLLECTION, GroupBy.key("x") .initialDocument(new Document("count", 0)).reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class); @@ -109,7 +102,7 @@ public void simpleGroupWithKeyFunction() { createGroupByData(); GroupByResults results = mongoTemplate .group( - "group_test_collection", GroupBy.keyFunction("function(doc) { return { x : doc.x }; }") + GROUP_TEST_COLLECTION, GroupBy.keyFunction("function(doc) { return { x : doc.x }; }") .initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class); @@ -120,7 +113,7 @@ public void simpleGroupWithKeyFunction() { public void simpleGroupWithFunctionsAsResources() { createGroupByData(); - GroupByResults results = mongoTemplate.group("group_test_collection", + GroupByResults results = mongoTemplate.group(GROUP_TEST_COLLECTION, GroupBy.keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }") .reduceFunction("classpath:groupReduce.js"), XObject.class); @@ -132,7 +125,7 @@ public void simpleGroupWithFunctionsAsResources() { public void simpleGroupWithQueryAndFunctionsAsResources() { createGroupByData(); - GroupByResults results = mongoTemplate.group(where("x").gt(0), "group_test_collection", + GroupByResults results = mongoTemplate.group(where("x").gt(0), GROUP_TEST_COLLECTION, keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }") .reduceFunction("classpath:groupReduce.js"), XObject.class); @@ -162,7 +155,7 @@ private void assertMapReduceResults(GroupByResults results) { private void createGroupByData() { - MongoCollection c = mongoTemplate.getDb().getCollection("group_test_collection", Document.class); + MongoCollection c = mongoTemplate.getDb().getCollection(GROUP_TEST_COLLECTION, Document.class); c.insertOne(new Document("x", 1)); c.insertOne(new Document("x", 1)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index 216e765b97..e0f255352b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -25,6 +25,7 @@ import lombok.Data; import lombok.NoArgsConstructor; +import java.time.Duration; import java.time.Instant; import java.util.List; import java.util.concurrent.LinkedBlockingDeque; @@ -41,8 +42,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.ChangeStreamOptions; import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions; import org.springframework.data.mongodb.core.messaging.ChangeStreamTask.ChangeStreamEventMessage; import org.springframework.data.mongodb.core.messaging.Message.MessageProperties; import org.springframework.data.mongodb.core.messaging.SubscriptionUtils.*; @@ -50,11 +52,11 @@ import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.ReplSetClient; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; @@ -65,14 +67,15 @@ * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith({ MongoClientExtension.class }) +@ExtendWith({ MongoTemplateExtension.class }) @EnableIfReplicaSetAvailable public class ChangeStreamTests { - static @ReplSetClient MongoClient mongoClient; - static ThreadPoolExecutor executor; - MongoTemplate template; + + @Template(initialEntitySet = User.class, replicaSet = true) // + static MongoTestTemplate template; + MessageListenerContainer container; User jellyBelly; @@ -87,7 +90,6 @@ public static void beforeClass() { @BeforeEach public void setUp() { - template = new MongoTemplate(mongoClient, "change-stream-tests"); template.dropCollection(User.class); container = new DefaultMessageListenerContainer(template, executor); @@ -123,7 +125,8 @@ public static void afterClass() { public void readsPlainDocumentMessageCorrectly() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, Document.class); awaitSubscription(subscription); @@ -148,6 +151,7 @@ public void useSimpleAggregationToFilterMessages() throws InterruptedException { ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // .collection("user") // .filter(newAggregation(match(where("age").is(7)))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -174,6 +178,7 @@ public void useAggregationToFilterMessages() throws InterruptedException { .collection("user") // .filter(newAggregation(match( new Criteria().orOperator(where("user_name").is("huffyFluffy"), where("user_name").is("jellyBelly"))))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -200,6 +205,7 @@ public void mapsTypedAggregationToFilterMessages() throws InterruptedException { .publishTo(messageListener) // .filter(newAggregation(User.class, match(new Criteria().orOperator(where("userName").is("huffyFluffy"), where("userName").is("jellyBelly"))))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -209,7 +215,7 @@ public void mapsTypedAggregationToFilterMessages() throws InterruptedException { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 2); List messageBodies = messageListener.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -225,6 +231,7 @@ public void mapsReservedWordsCorrectly() throws InterruptedException { .collection("user") // .publishTo(messageListener) // .filter(newAggregation(User.class, match(where("operationType").is("replace")))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -240,7 +247,7 @@ public void mapsReservedWordsCorrectly() throws InterruptedException { template.save(replacement); - awaitMessages(messageListener); + awaitMessages(messageListener, 1); List messageBodies = messageListener.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -256,6 +263,7 @@ public void plainAggregationPipelineToFilterMessages() throws InterruptedExcepti .collection("user") // .publishTo(messageListener) // .filter(new Document("$match", new Document("fullDocument.user_name", "sugarSplashy"))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -265,7 +273,7 @@ public void plainAggregationPipelineToFilterMessages() throws InterruptedExcepti template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 1); List messageBodies = messageListener.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -277,7 +285,9 @@ public void plainAggregationPipelineToFilterMessages() throws InterruptedExcepti public void resumesCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); - Subscription subscription1 = container.register(new ChangeStreamRequest<>(messageListener1, () -> "user"), + Subscription subscription1 = container.register( + new ChangeStreamRequest<>(messageListener1, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())), User.class); awaitSubscription(subscription1); @@ -292,12 +302,12 @@ public void resumesCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener2 = new CollectingMessageListener<>(); ChangeStreamRequest subSequentRequest = ChangeStreamRequest.builder().collection("user") - .publishTo(messageListener2).resumeToken(resumeToken).build(); + .publishTo(messageListener2).resumeToken(resumeToken).maxAwaitTime(Duration.ofMillis(10)).build(); Subscription subscription2 = container.register(subSequentRequest, User.class); awaitSubscription(subscription2); - awaitMessages(messageListener2); + awaitMessages(messageListener2, 2); List messageBodies = messageListener2.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -309,7 +319,8 @@ public void resumesCorrectly() throws InterruptedException { public void readsAndConvertsMessageBodyCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, User.class); awaitSubscription(subscription); @@ -330,7 +341,8 @@ public void readsAndConvertsMessageBodyCorrectly() throws InterruptedException { public void readsAndConvertsUpdateMessageBodyCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, User.class); awaitSubscription(subscription); @@ -349,7 +361,8 @@ public void readsAndConvertsUpdateMessageBodyCorrectly() throws InterruptedExcep public void readsOnlyDiffForUpdateWhenNotMappedToDomainType() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, Document.class); awaitSubscription(subscription); @@ -372,6 +385,7 @@ public void readsOnlyDiffForUpdateWhenOptionsDeclareDefaultExplicitly() throws I ChangeStreamRequest request = ChangeStreamRequest.builder() // .collection("user") // .fullDocumentLookup(FullDocument.DEFAULT) // + .maxAwaitTime(Duration.ofMillis(10)) // .publishTo(messageListener).build(); Subscription subscription = container.register(request, User.class); @@ -395,6 +409,7 @@ public void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecifie ChangeStreamRequest request = ChangeStreamRequest.builder() // .collection("user") // .fullDocumentLookup(FullDocument.UPDATE_LOOKUP) // + .maxAwaitTime(Duration.ofMillis(10)) // .publishTo(messageListener).build(); Subscription subscription = container.register(request, Document.class); @@ -417,7 +432,9 @@ public void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecifie public void resumeAtTimestampCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); - Subscription subscription1 = container.register(new ChangeStreamRequest<>(messageListener1, () -> "user"), + Subscription subscription1 = container.register( + new ChangeStreamRequest<>(messageListener1, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())), User.class); awaitSubscription(subscription1); @@ -441,12 +458,13 @@ public void resumeAtTimestampCorrectly() throws InterruptedException { .collection("user") // .resumeAt(resumeAt) // .publishTo(messageListener2) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription2 = container.register(subSequentRequest, User.class); awaitSubscription(subscription2); - awaitMessages(messageListener2); + awaitMessages(messageListener2, 2); List messageBodies = messageListener2.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -461,6 +479,7 @@ public void filterOnNestedElementWorksCorrectly() throws InterruptedException { ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // .collection("user") // .filter(newAggregation(User.class, match(where("address.street").is("flower street")))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -495,6 +514,7 @@ public void filterOnUpdateDescriptionElement() throws InterruptedException { ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // .collection("user") // .filter(newAggregation(User.class, match(where("updateDescription.updatedFields.address").exists(true)))) // + .maxAwaitTime(Duration.ofMillis(10)) // .fullDocumentLookup(FullDocument.UPDATE_LOOKUP).build(); Subscription subscription = container.register(request, User.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index 52d2581b55..e2cedf16e5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -30,22 +30,21 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.ChangeStreamOptions; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; -import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; -import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ErrorHandler; -import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.changestream.ChangeStreamDocument; @@ -55,36 +54,31 @@ * * @author Christoph Strobl */ -@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) +@ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) public class DefaultMessageListenerContainerTests { - public static final String DATABASE_NAME = "change-stream-events"; - public static final String COLLECTION_NAME = "collection-1"; - public static final String COLLECTION_2_NAME = "collection-2"; + static final String DATABASE_NAME = "change-stream-events"; + static final String COLLECTION_NAME = "collection-1"; + static final String COLLECTION_2_NAME = "collection-2"; + + static final Duration TIMEOUT = Duration.ofSeconds(2); - public static final Duration TIMEOUT = Duration.ofSeconds(2); + @Template(database = DATABASE_NAME, initialEntitySet = Person.class) // + static MongoTemplate template; - static @Client MongoClient client; + MongoDatabaseFactory dbFactory = template.getMongoDbFactory(); - MongoDatabaseFactory dbFactory; - MongoCollection collection; - MongoCollection collection2; + MongoCollection collection = template.getCollection(COLLECTION_NAME); + MongoCollection collection2 = template.getCollection(COLLECTION_2_NAME); private CollectingMessageListener messageListener; - private MongoTemplate template; @BeforeEach void beforeEach() { - dbFactory = new SimpleMongoClientDatabaseFactory(client, DATABASE_NAME); - template = new MongoTemplate(dbFactory); - template.dropCollection(COLLECTION_NAME); template.dropCollection(COLLECTION_2_NAME); - collection = template.getCollection(COLLECTION_NAME); - collection2 = template.getCollection(COLLECTION_2_NAME); - messageListener = new CollectingMessageListener<>(); } @@ -94,8 +88,7 @@ void beforeEach() { public void shouldCollectMappedChangeStreamMessagesCorrectly() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Person.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Person.class); container.start(); awaitSubscription(subscription, TIMEOUT); @@ -126,7 +119,7 @@ public void shouldNotifyErrorHandlerOnErrorInListener() throws InterruptedExcept messageListener.onMessage(message); } - }, () -> COLLECTION_NAME), Person.class, errorHandler); + }, options()), Person.class, errorHandler); container.start(); awaitSubscription(subscription, TIMEOUT); @@ -145,8 +138,7 @@ public void shouldNotifyErrorHandlerOnErrorInListener() throws InterruptedExcept public void shouldNoLongerReceiveMessagesWhenContainerStopped() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Document.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Document.class); container.start(); awaitSubscription(subscription, TIMEOUT); @@ -175,8 +167,7 @@ public void shouldReceiveMessagesWhenAddingRequestToAlreadyStartedContainer() th Document unexpected = new Document("_id", "id-1").append("value", "foo"); collection.insertOne(unexpected); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Document.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Document.class); awaitSubscription(subscription, TIMEOUT); @@ -195,8 +186,7 @@ public void shouldReceiveMessagesWhenAddingRequestToAlreadyStartedContainer() th public void shouldStartReceivingMessagesWhenContainerStarts() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Document.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Document.class); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -228,8 +218,8 @@ public void tailableCursor() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); container.start(); - awaitSubscription( - container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), Document.class), TIMEOUT); + awaitSubscription(container.register(new TailableCursorRequest(messageListener, options()), Document.class), + TIMEOUT); collection.insertOne(new Document("_id", "id-2").append("value", "bar")); @@ -248,8 +238,8 @@ public void tailableCursorOnEmptyCollection() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); container.start(); - awaitSubscription( - container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), Document.class), TIMEOUT); + awaitSubscription(container.register(new TailableCursorRequest(messageListener, options()), Document.class), + TIMEOUT); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); collection.insertOne(new Document("_id", "id-2").append("value", "bar")); @@ -271,7 +261,7 @@ public void abortsSubscriptionOnError() throws InterruptedException { collection.insertOne(new Document("_id", "id-1").append("value", "foo")); - Subscription subscription = container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), + Subscription subscription = container.register(new TailableCursorRequest(messageListener, options()), Document.class); awaitSubscription(subscription); @@ -304,7 +294,7 @@ public void callsDefaultErrorHandlerOnError() throws InterruptedException { try { container.start(); - Subscription subscription = container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), + Subscription subscription = container.register(new TailableCursorRequest(messageListener, options()), Document.class); SubscriptionUtils.awaitSubscription(subscription); @@ -330,12 +320,12 @@ public void runsMoreThanOneTaskAtOnce() throws InterruptedException { container.start(); CollectingMessageListener tailableListener = new CollectingMessageListener<>(); - Subscription tailableSubscription = container - .register(new TailableCursorRequest(tailableListener, () -> COLLECTION_NAME), Document.class); + Subscription tailableSubscription = container.register(new TailableCursorRequest(tailableListener, options()), + Document.class); CollectingMessageListener, Document> changeStreamListener = new CollectingMessageListener<>(); - Subscription changeStreamSubscription = container - .register(new ChangeStreamRequest(changeStreamListener, () -> COLLECTION_NAME), Document.class); + Subscription changeStreamSubscription = container.register(new ChangeStreamRequest(changeStreamListener, options()), + Document.class); awaitSubscriptions(tailableSubscription, changeStreamSubscription); @@ -390,4 +380,9 @@ public Person(String id, String firstname) { this.firstname = firstname; } } + + static ChangeStreamRequestOptions options() { + return new ChangeStreamRequestOptions(DATABASE_NAME, COLLECTION_NAME, Duration.ofMillis(10), + ChangeStreamOptions.builder().build()); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java index 2e723df5b1..52fff4387b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java @@ -162,7 +162,7 @@ public void filtersMessagesCorrectly() throws InterruptedException { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 2); assertThat(messageListener.getMessages().stream().map(Message::getBody)).hasSize(2).doesNotContain(sugarSplashy); } @@ -183,7 +183,7 @@ public void mapsFilterToDomainType() throws InterruptedException { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 1); assertThat(messageListener.getMessages().stream().map(Message::getBody)).hasSize(1).containsExactly(sugarSplashy); } @@ -201,7 +201,7 @@ public void emitsFromStart() throws InterruptedException { template.save(sugarSplashy); - awaitMessages(messageListener); + awaitMessages(messageListener, 3); assertThat(messageListener.getMessages().stream().map(Message::getBody)).hasSize(3).containsExactly(jellyBelly, huffyFluffy, sugarSplashy); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java index dc3e862be9..783e8a0a4a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java @@ -26,29 +26,26 @@ import java.util.Arrays; import org.bson.types.Binary; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.Base64Utils; -import com.mongodb.client.MongoClient; - /** * Integration tests for {@link Criteria} usage as part of a {@link Query}. * * @author Christoph Strobl * @author Andreas Zink */ -public class CriteriaTests { +@ExtendWith(MongoTemplateExtension.class) +class CriteriaTests { - static MongoClient client; - MongoOperations ops; + @Template(initialEntitySet = { DocumentWithBitmask.class }) // + static MongoTestTemplate ops; static final DocumentWithBitmask FIFTY_FOUR/*00110110*/ = new DocumentWithBitmask("1", Integer.valueOf(54), Integer.toBinaryString(54)); @@ -59,22 +56,10 @@ public class CriteriaTests { static final DocumentWithBitmask ONE_HUNDRED_TWO/*01100110*/ = new DocumentWithBitmask("4", new Binary(Base64Utils.decodeFromString("Zg==")), "01100110"); - @BeforeClass - public static void beforeClass() { - client = MongoTestUtils.client(); - } - - @AfterClass - public static void afterClass() { - client.close(); - } - - @Before - public void setUp() { - - ops = new MongoTemplate(client, "criteria-tests"); + @BeforeEach + void beforeEach() { - ops.dropCollection(DocumentWithBitmask.class); + ops.flush(); ops.insert(FIFTY_FOUR); ops.insert(TWENTY_INT); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java index d0b4b70823..5c0dd7708d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java @@ -23,26 +23,27 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.domain.PageRequest; -import org.springframework.data.mongodb.config.AbstractIntegrationTests; -import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.index.IndexDefinition; import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.Language; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.query.TextQueryTests.FullTextDoc.FullTextDocBuilder; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * @author Christoph Strobl * @author Mark Paluch */ -public class TextQueryTests extends AbstractIntegrationTests { +@ExtendWith(MongoTemplateExtension.class) +public class TextQueryTests { private static final FullTextDoc BAKE = new FullTextDocBuilder().headline("bake").build(); private static final FullTextDoc COFFEE = new FullTextDocBuilder().subHeadline("coffee").build(); @@ -53,11 +54,14 @@ public class TextQueryTests extends AbstractIntegrationTests { private static final FullTextDoc FRENCH_MILK = new FullTextDocBuilder().headline("leche").lanugage("french").build(); private static final FullTextDoc MILK_AND_SUGAR = new FullTextDocBuilder().headline("milk and sugar").build(); - private @Autowired MongoOperations template; + @Template(initialEntitySet = FullTextDoc.class) // + static MongoTestTemplate template; - @Before + @BeforeEach public void setUp() { + template.flush(); + IndexOperations indexOps = template.indexOps(FullTextDoc.class); indexOps.dropAllIndexes(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java index 37d028c80a..c489fd42c8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java @@ -69,6 +69,8 @@ public MongoClient mongoClient() { protected String getDatabaseName() { return "json-schema-tests"; } + + } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java index 43af21cd94..e590c529c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java @@ -21,7 +21,9 @@ import reactor.test.StepVerifier; import java.time.Duration; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -65,6 +67,11 @@ public MongoClient reactiveMongoClient() { protected String getDatabaseName() { return "json-schema-tests"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.emptySet(); + } } @Autowired ReactiveMongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java index fcb1cd91dc..2213ed2dcf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java @@ -19,12 +19,10 @@ import java.net.UnknownHostException; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.client.MongoClient; @@ -35,11 +33,10 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoClientExtension.class) public class MongoMonitorIntegrationTests { - @Autowired MongoClient mongoClient; + static @Client MongoClient mongoClient; @Test public void serverInfo() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java index a9488c1cf7..73f53e456c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java @@ -21,12 +21,15 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @@ -47,7 +50,7 @@ public class ComplexIdRepositoryIntegrationTests { static @Client MongoClient mongoClient; @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = UserWithComplexIdRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Override @@ -60,6 +63,10 @@ public MongoClient mongoClient() { return mongoClient; } + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired UserWithComplexIdRepository repo; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java index f78c21a044..75c83049d9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java @@ -20,35 +20,26 @@ import java.util.Arrays; import java.util.List; -import org.junit.After; -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.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder; import org.springframework.data.mongodb.core.index.TextIndexed; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.query.TextCriteria; import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.ClassUtils; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ObjectUtils; -import com.mongodb.client.MongoClient; - /** * Integration tests for text searches on repository. * @@ -56,12 +47,9 @@ * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith(MongoTemplateExtension.class) public class MongoRepositoryTextSearchIntegrationTests { - public static @ClassRule MongoVersionRule versionRule = MongoVersionRule.atLeast(new Version(2, 6, 0)); - private static final FullTextDocument PASSENGER_57 = new FullTextDocument("1", "Passenger 57", "Passenger 57 is an action film that stars Wesley Snipes and Bruce Payne."); private static final FullTextDocument DEMOLITION_MAN = new FullTextDocument("2", "Demolition Man", @@ -69,20 +57,21 @@ public class MongoRepositoryTextSearchIntegrationTests { private static final FullTextDocument DROP_ZONE = new FullTextDocument("3", "Drop Zone", "Drop Zone is an action film featuring Wesley Snipes and Gary Busey."); - @Autowired MongoTemplate template; - FullTextRepository repo; + @Template(initialEntitySet = FullTextDocument.class) // + static MongoTestTemplate template; + + FullTextRepository repo = new MongoRepositoryFactory(this.template).getRepository(FullTextRepository.class); - @Before + @BeforeEach public void setUp() { template.indexOps(FullTextDocument.class) .ensureIndex(new TextIndexDefinitionBuilder().onField("title").onField("content").build()); - this.repo = new MongoRepositoryFactory(this.template).getRepository(FullTextRepository.class); } - @After + @AfterEach public void tearDown() { - template.dropCollection(FullTextDocument.class); + template.flush(); } @Test // DATAMONGO-973 @@ -193,21 +182,6 @@ private void initRepoWithDefaultDocuments() { repo.saveAll(Arrays.asList(PASSENGER_57, DEMOLITION_MAN, DROP_ZONE)); } - @org.springframework.context.annotation.Configuration - public static class Configuration extends AbstractMongoClientConfiguration { - - @Override - protected String getDatabaseName() { - return ClassUtils.getShortNameAsProperty(MongoRepositoryTextSearchIntegrationTests.class); - } - - @Override - public MongoClient mongoClient() { - return MongoTestUtils.client(); - } - - } - static class FullTextDocument { private @Id String id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index ad3e109437..ad78b59692 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -19,7 +19,9 @@ import static org.springframework.data.mongodb.test.util.MongoTestUtils.*; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.bson.Document; @@ -29,7 +31,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.domain.Persistable; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; @@ -68,7 +72,7 @@ public class PersonRepositoryTransactionalTests { static @ReplSetClient MongoClient mongoClient; @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PersonRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Bean @@ -85,6 +89,11 @@ protected String getDatabaseName() { MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.singleton(Person.class); + } } @Autowired MongoClient client; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java index 5bc6f3b540..3330c112db 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java @@ -20,7 +20,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; @@ -39,7 +41,7 @@ public class MongoRepositoriesRegistrarIntegrationTests { @Configuration - @EnableMongoRepositories(basePackages = "org.springframework.data.mongodb.repository") + @EnableMongoRepositories(basePackages = "org.springframework.data.mongodb.repository", includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PersonRepository.class)) static class Config { @Bean diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java index 0ce5f834b5..6ef07a4189 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java @@ -20,7 +20,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.test.context.ContextConfiguration; @@ -36,7 +38,7 @@ public class ComposedRepositoryImplementationTests { @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ComposedRepository.class)) @ImportResource("classpath:infrastructure.xml") static class Config {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java index 67fa8b272d..a1e202a217 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java @@ -23,7 +23,9 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; @@ -40,7 +42,7 @@ public class CustomReactiveRepositoryImplementationTests { @Configuration - @EnableReactiveMongoRepositories + @EnableReactiveMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CustomReactiveMongoRepository.class)) @ImportResource("classpath:reactive-infrastructure.xml") static class Config {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java index df1b859a5d..b813e3e396 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java @@ -23,7 +23,9 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @@ -40,7 +42,7 @@ public class CustomRepositoryImplementationTests { @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CustomMongoRepository.class)) @ImportResource("classpath:infrastructure.xml") static class Config {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java index e83d009aaa..270fb99947 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java @@ -20,7 +20,9 @@ import reactor.test.StepVerifier; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashSet; +import java.util.Set; import org.junit.After; import org.junit.Before; @@ -84,6 +86,11 @@ public MongoClient reactiveMongoClient() { protected String getDatabaseName() { return "reactive"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(Person.class); + } } @BeforeClass diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 8688a57686..9cf066acea 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.repository.support; import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.Assumptions.*; import static org.springframework.data.domain.ExampleMatcher.*; import java.util.ArrayList; @@ -28,18 +27,15 @@ import java.util.Set; import java.util.UUID; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.ExampleMatcher.*; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.MongoTransactionManager; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Collation; @@ -48,11 +44,12 @@ import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.support.TransactionTemplate; @@ -62,22 +59,22 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) public class SimpleMongoRepositoryTests { - @Autowired private MongoTemplate template; - public @Rule MongoVersionRule mongoVersion = MongoVersionRule.any(); + @Template(initialEntitySet = Person.class) // + static MongoTestTemplate template; private Person oliver, dave, carter, boyd, stefan, leroi, alicia; private List all; private MongoEntityInformation personEntityInformation = new CustomizedPersonInformation(); - private SimpleMongoRepository repository; + private SimpleMongoRepository repository = new SimpleMongoRepository<>(personEntityInformation, + template); - @Before + @BeforeEach public void setUp() { - repository = new SimpleMongoRepository(personEntityInformation, template); + repository.deleteAll(); oliver = new Person("Oliver August", "Matthews", 4); @@ -393,11 +390,10 @@ public void saveAllUsesEntityCollection() { } @Test // DATAMONGO-2130 - @MongoVersion(asOf = "4.0") + @EnableIfReplicaSetAvailable + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void countShouldBePossibleInTransaction() { - assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - MongoTransactionManager txmgr = new MongoTransactionManager(template.getMongoDbFactory()); TransactionTemplate tt = new TransactionTemplate(txmgr); tt.afterPropertiesSet(); @@ -418,11 +414,10 @@ public void countShouldBePossibleInTransaction() { } @Test // DATAMONGO-2130 - @MongoVersion(asOf = "4.0") + @EnableIfReplicaSetAvailable + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void existsShouldBePossibleInTransaction() { - assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - MongoTransactionManager txmgr = new MongoTransactionManager(template.getMongoDbFactory()); TransactionTemplate tt = new TransactionTemplate(txmgr); tt.afterPropertiesSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java index 98bdc44f0a..4d1fdea644 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java @@ -20,6 +20,11 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -64,6 +69,11 @@ public MongoClient mongoClient() { protected String getDatabaseName() { return "database"; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>(Arrays.asList(VersionedPerson.class)); + } } @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java index e727f61148..23b2405f94 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java @@ -18,6 +18,9 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; +import java.util.Set; + import reactor.test.StepVerifier; import org.junit.Before; @@ -57,6 +60,11 @@ public MongoClient reactiveMongoClient() { protected String getDatabaseName() { return "database"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(VersionedPerson.class); + } } @Autowired // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java index 2da900ca09..b791fb1b91 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java @@ -18,7 +18,6 @@ import static org.junit.platform.commons.util.AnnotationUtils.*; import static org.junit.platform.commons.util.ReflectionUtils.*; -import java.io.Closeable; import java.lang.reflect.Field; import java.util.function.Predicate; @@ -36,7 +35,6 @@ import org.junit.platform.commons.util.ReflectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.util.ClassUtils; import com.mongodb.client.MongoClient; @@ -52,14 +50,17 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After private static final Logger LOGGER = LoggerFactory.getLogger(MongoClientExtension.class); - private static final Namespace NAMESPACE = Namespace.create(MongoClientExtension.class); - private static final String SYNC_KEY = "mongo.client.sync"; - private static final String REACTIVE_KEY = "mongo.client.reactive"; - private static final String SYNC_REPLSET_KEY = "mongo.client.replset.sync"; - private static final String REACTIVE_REPLSET_KEY = "mongo.client.replset.reactive"; + private static final Namespace NAMESPACE = MongoExtensions.Client.NAMESPACE; + + private static final String SYNC_KEY = MongoExtensions.Client.SYNC_KEY; + private static final String REACTIVE_KEY = MongoExtensions.Client.REACTIVE_KEY; + private static final String SYNC_REPLSET_KEY = MongoExtensions.Client.SYNC_REPLSET_KEY; + private static final String REACTIVE_REPLSET_KEY = MongoExtensions.Client.REACTIVE_REPLSET_KEY; @Override - public void afterAll(ExtensionContext extensionContext) throws Exception {} + public void afterAll(ExtensionContext extensionContext) throws Exception { + + } @Override public void beforeAll(ExtensionContext context) throws Exception { @@ -87,7 +88,7 @@ private void injectFields(ExtensionContext context, Object testInstance, Predica }); } - private Object getMongoClient(Class type, ExtensionContext extensionContext, boolean replSet) { + protected Object getMongoClient(Class type, ExtensionContext extensionContext, boolean replSet) { Store store = extensionContext.getStore(NAMESPACE); @@ -120,6 +121,12 @@ private SyncClientHolder syncClient(boolean replSet) { return new SyncClientHolder(replSet ? MongoTestUtils.replSetClient() : MongoTestUtils.client()); } + protected boolean holdsReplSetClient(ExtensionContext context) { + + Store store = context.getStore(NAMESPACE); + return store.get(SYNC_REPLSET_KEY) != null || store.get(REACTIVE_REPLSET_KEY) != null; + } + private void assertValidFieldCandidate(Field field) { assertSupportedType("field", field.getType()); @@ -137,14 +144,6 @@ private void assertSupportedType(String target, Class type) { } } - private void closeClient(Store store, String key) { - - Closeable client = store.remove(key, Closeable.class); - if (client != null) { - - } - } - @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { @@ -164,7 +163,7 @@ static class SyncClientHolder implements Store.CloseableResource { final MongoClient client; - public SyncClientHolder(MongoClient client) { + SyncClientHolder(MongoClient client) { this.client = client; } @@ -182,7 +181,7 @@ static class ReactiveClientHolder implements Store.CloseableResource { final com.mongodb.reactivestreams.client.MongoClient client; - public ReactiveClientHolder(com.mongodb.reactivestreams.client.MongoClient client) { + ReactiveClientHolder(com.mongodb.reactivestreams.client.MongoClient client) { this.client = client; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java new file mode 100644 index 0000000000..5f45cef1aa --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; + +/** + * @author Christoph Strobl + */ +class MongoExtensions { + + static class Client { + + static final Namespace NAMESPACE = Namespace.create(MongoClientExtension.class); + static final String SYNC_KEY = "mongo.client.sync"; + static final String REACTIVE_KEY = "mongo.client.reactive"; + static final String SYNC_REPLSET_KEY = "mongo.client.replset.sync"; + static final String REACTIVE_REPLSET_KEY = "mongo.client.replset.reactive"; + } + + static class Termplate { + + static final Namespace NAMESPACE = Namespace.create(MongoTemplateExtension.class); + static final String SYNC = "mongo.template.sync"; + static final String REACTIVE = "mongo.template.reactive"; + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java new file mode 100644 index 0000000000..c88425ba8a --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java @@ -0,0 +1,147 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import static org.junit.platform.commons.util.AnnotationUtils.*; +import static org.junit.platform.commons.util.ReflectionUtils.*; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.function.Predicate; + +import org.junit.jupiter.api.extension.ExtensionConfigurationException; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.platform.commons.util.ExceptionUtils; +import org.junit.platform.commons.util.ReflectionUtils; +import org.junit.platform.commons.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.mapping.model.CamelCaseSplittingFieldNamingStrategy; +import org.springframework.data.mongodb.test.util.MongoExtensions.Termplate; +import org.springframework.data.util.ParsingUtils; +import org.springframework.util.ClassUtils; + +/** + * @author Christoph Strobl + */ +public class MongoTemplateExtension extends MongoClientExtension { + + private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplateExtension.class); + CamelCaseSplittingFieldNamingStrategy splitter = new CamelCaseSplittingFieldNamingStrategy("-"); + + @Override + public void afterAll(ExtensionContext context) throws Exception { + + } + + @Override + public void beforeAll(ExtensionContext context) throws Exception { + super.beforeAll(context); + + injectFields(context, null, ReflectionUtils::isStatic); + } + + private void injectFields(ExtensionContext context, Object testInstance, Predicate predicate) { + + findAnnotatedFields(context.getRequiredTestClass(), Template.class, predicate).forEach(field -> { + assertValidFieldCandidate(field); + try { + + makeAccessible(field).set(testInstance, + getMongoTemplate(field.getType(), field.getAnnotation(Template.class), context)); + } catch (Throwable t) { + ExceptionUtils.throwAsUncheckedException(t); + } + }); + } + + private void assertValidFieldCandidate(Field field) { + + assertSupportedType("field", field.getType()); + if (isPrivate(field)) { + throw new ExtensionConfigurationException("@MongoClient field [" + field + "] must not be private."); + } + } + + private void assertSupportedType(String target, Class type) { + + if (!ClassUtils.isAssignable(org.springframework.data.mongodb.core.MongoOperations.class, type) + && !ClassUtils.isAssignable(org.springframework.data.mongodb.core.ReactiveMongoOperations.class, type)) { + throw new ExtensionConfigurationException("Can only resolve @MongoClient " + target + " of type " + + org.springframework.data.mongodb.core.MongoOperations.class.getName() + " or " + + org.springframework.data.mongodb.core.ReactiveMongoOperations.class.getName() + " but was: " + + type.getName()); + } + } + + private Object getMongoTemplate(Class type, Template options, ExtensionContext extensionContext) { + + Store templateStore = extensionContext.getStore(MongoExtensions.Termplate.NAMESPACE); + + boolean replSetClient = holdsReplSetClient(extensionContext) || options.replicaSet(); + + String dbName = StringUtils.isNotBlank(options.database()) ? options.database() + : extensionContext.getTestClass().map(it -> { + List target = ParsingUtils.splitCamelCaseToLower(it.getSimpleName()); + return org.springframework.util.StringUtils.collectionToDelimitedString(target, "-"); + }).orElse("database"); + + if (ClassUtils.isAssignable(org.springframework.data.mongodb.core.MongoOperations.class, type)) { + + String key = Termplate.SYNC + "-" + dbName; + return templateStore.getOrComputeIfAbsent(key, it -> { + + com.mongodb.client.MongoClient client = (com.mongodb.client.MongoClient) getMongoClient( + com.mongodb.client.MongoClient.class, extensionContext, replSetClient); + return new MongoTestTemplate(client, dbName, options.initialEntitySet()); + }); + } + + if (ClassUtils.isAssignable(org.springframework.data.mongodb.core.ReactiveMongoOperations.class, type)) { + + String key = Termplate.REACTIVE + "-" + dbName; + return templateStore.getOrComputeIfAbsent(key, it -> { + + com.mongodb.reactivestreams.client.MongoClient client = (com.mongodb.reactivestreams.client.MongoClient) getMongoClient( + com.mongodb.reactivestreams.client.MongoClient.class, extensionContext, replSetClient); + return new ReactiveMongoTestTemplate(client, dbName, options.initialEntitySet()); + }); + } + + throw new IllegalStateException("Damn - something went wrong."); + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return super.supportsParameter(parameterContext, extensionContext) || parameterContext.isAnnotated(Template.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + + if (parameterContext.getParameter().getAnnotation(Template.class) == null) { + return super.resolveParameter(parameterContext, extensionContext); + } + Class parameterType = parameterContext.getParameter().getType(); + return getMongoTemplate(parameterType, parameterContext.getParameter().getAnnotation(Template.class), + extensionContext); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java new file mode 100644 index 0000000000..bf14555ea5 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java @@ -0,0 +1,144 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import java.util.Arrays; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.bson.Document; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.mongodb.core.MongoTemplate; + +import com.mongodb.MongoWriteException; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; + +/** + * A {@link MongoTemplate} with configuration hooks and extension suitable for tests. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class MongoTestTemplate extends MongoTemplate { + + private final MongoTestTemplateConfiguration cfg; + + public MongoTestTemplate(MongoClient client, String database, Class... initialEntities) { + this(cfg -> { + cfg.configureDatabaseFactory(it -> { + + it.client(client); + it.defaultDb(database); + }); + + cfg.configureMappingContext(it -> { + + it.autocreateIndex(false); + it.intitalEntitySet(initialEntities); + }); + }); + } + + public MongoTestTemplate(Consumer cfg) { + + this(new Supplier() { + @Override + public MongoTestTemplateConfiguration get() { + + MongoTestTemplateConfiguration config = new MongoTestTemplateConfiguration(); + cfg.accept(config); + return config; + } + }); + } + + public MongoTestTemplate(Supplier config) { + this(config.get()); + } + + public MongoTestTemplate(MongoTestTemplateConfiguration config) { + super(config.databaseFactory(), config.mongoConverter()); + + ApplicationContext applicationContext = config.getApplicationContext(); + if (applicationContext != null) { + setApplicationContext(applicationContext); + } + + this.cfg = config; + } + + public void flush() { + flush(PersistentEntities.of(getConverter().getMappingContext()).stream().map(it -> getCollectionName(it.getType())) + .collect(Collectors.toList())); + } + + public void flushDatabase() { + flush(getDb().listCollectionNames()); + } + + public void flush(Iterable collections) { + + for (String collection : collections) { + MongoCollection mongoCollection = getCollection(collection); + try { + mongoCollection.deleteMany(new Document()); + } catch (MongoWriteException e) { + mongoCollection.drop(); + } + } + } + + public void flush(Class... entities) { + flush(Arrays.asList(entities).stream().map(this::getCollectionName).collect(Collectors.toList())); + } + + public void flush(String... collections) { + flush(Arrays.asList(collections)); + } + + public void flush(Object... objects) { + + flush(Arrays.asList(objects).stream().map(it -> { + + if (it instanceof String) { + return (String) it; + } + if (it instanceof Class) { + return getCollectionName((Class) it); + } + return it.toString(); + }).collect(Collectors.toList())); + } + + public void dropDatabase() { + getDb().drop(); + } + + public void dropIndexes(String... collections) { + for (String collection : collections) { + getCollection(collection).dropIndexes(); + } + } + + public void dropIndexes(Class... entities) { + for (Class entity : entities) { + getCollection(getCollectionName(entity)).dropIndexes(); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java new file mode 100644 index 0000000000..a3870957e5 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java @@ -0,0 +1,285 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.convert.CustomConversions; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener; +import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +public class MongoTestTemplateConfiguration { + + private final DatabaseFactoryConfigurer dbFactoryConfig = new DatabaseFactoryConfigurer(); + private final MappingContextConfigurer mappingContextConfigurer = new MappingContextConfigurer(); + private final MongoConverterConfigurer mongoConverterConfigurer = new MongoConverterConfigurer(); + private final AuditingConfigurer auditingConfigurer = new AuditingConfigurer(); + private final ApplicationContextConfigurer applicationContextConfigurer = new ApplicationContextConfigurer(); + + private MongoMappingContext mappingContext; + private MappingMongoConverter converter; + private ApplicationContext context; + + private com.mongodb.client.MongoClient syncClient; + private com.mongodb.reactivestreams.client.MongoClient reactiveClient; + private MongoDatabaseFactory syncFactory; + private SimpleReactiveMongoDatabaseFactory reactiveFactory; + + MongoConverter mongoConverter() { + + if (converter == null) { + + converter = new MappingMongoConverter(new DefaultDbRefResolver(databaseFactory()), mappingContext()); + + if (mongoConverterConfigurer.customConversions != null) { + converter.setCustomConversions(mongoConverterConfigurer.customConversions); + } + converter.afterPropertiesSet(); + } + + return converter; + } + + List> getApplicationEventListener() { + + ArrayList> listeners = new ArrayList<>(applicationContextConfigurer.listeners); + if (auditingConfigurer.hasAuditingHandler()) { + listeners.add(new AuditingEventListener(() -> auditingConfigurer.auditingHandlers(mappingContext()))); + } + return listeners; + } + + @Nullable + ApplicationContext getApplicationContext() { + + if (applicationContextConfigurer.applicationContext == null) { + return null; + } + + if (context != null) { + return context; + } + + context = applicationContextConfigurer.applicationContext; + + if (context instanceof ConfigurableApplicationContext) { + + ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) this.context; + getApplicationEventListener().forEach(configurableApplicationContext::addApplicationListener); + + configurableApplicationContext.refresh(); + } + return context; + } + + MongoMappingContext mappingContext() { + + if (mappingContext == null) { + + mappingContext = new MongoMappingContext(); + mappingContext.setInitialEntitySet(mappingContextConfigurer.initialEntitySet()); + mappingContext.setAutoIndexCreation(mappingContextConfigurer.autocreateIndex); + mappingContext.afterPropertiesSet(); + } + + return mappingContext; + } + + MongoDatabaseFactory databaseFactory() { + + if (syncFactory == null) { + syncFactory = new SimpleMongoClientDatabaseFactory(syncClient(), defaultDatabase()); + } + + return syncFactory; + } + + ReactiveMongoDatabaseFactory reactiveDatabaseFactory() { + + if (reactiveFactory == null) { + reactiveFactory = new SimpleReactiveMongoDatabaseFactory(reactiveClient(), defaultDatabase()); + } + + return reactiveFactory; + } + + public MongoTestTemplateConfiguration configureDatabaseFactory(Consumer dbFactory) { + + dbFactory.accept(dbFactoryConfig); + return this; + } + + public MongoTestTemplateConfiguration configureMappingContext( + Consumer mappingContextConfigurerConsumer) { + mappingContextConfigurerConsumer.accept(mappingContextConfigurer); + return this; + } + + public MongoTestTemplateConfiguration configureApplicationContext( + Consumer applicationContextConfigurerConsumer) { + + applicationContextConfigurerConsumer.accept(applicationContextConfigurer); + return this; + } + + public MongoTestTemplateConfiguration configureAuditing(Consumer auditingConfigurerConsumer) { + + auditingConfigurerConsumer.accept(auditingConfigurer); + return this; + } + + public MongoTestTemplateConfiguration configureConversion( + Consumer mongoConverterConfigurerConsumer) { + + mongoConverterConfigurerConsumer.accept(mongoConverterConfigurer); + return this; + } + + com.mongodb.client.MongoClient syncClient() { + + if (syncClient == null) { + syncClient = dbFactoryConfig.syncClient != null ? dbFactoryConfig.syncClient : MongoTestUtils.client(); + } + + return syncClient; + } + + com.mongodb.reactivestreams.client.MongoClient reactiveClient() { + + if (reactiveClient == null) { + reactiveClient = dbFactoryConfig.reactiveClient != null ? dbFactoryConfig.reactiveClient + : MongoTestUtils.reactiveClient(); + } + + return reactiveClient; + } + + String defaultDatabase() { + return dbFactoryConfig.defaultDatabase != null ? dbFactoryConfig.defaultDatabase : "test"; + } + + public static class DatabaseFactoryConfigurer { + + com.mongodb.client.MongoClient syncClient; + com.mongodb.reactivestreams.client.MongoClient reactiveClient; + String defaultDatabase; + + public void client(com.mongodb.client.MongoClient client) { + this.syncClient = client; + } + + public void client(com.mongodb.reactivestreams.client.MongoClient client) { + this.reactiveClient = client; + } + + public void defaultDb(String defaultDatabase) { + this.defaultDatabase = defaultDatabase; + } + } + + public static class MongoConverterConfigurer { + + CustomConversions customConversions; + + public void customConversions(CustomConversions customConversions) { + this.customConversions = customConversions; + } + + public void customConverters(Converter... converters) { + customConversions(new MongoCustomConversions(Arrays.asList(converters))); + } + } + + public static class MappingContextConfigurer { + + Set> intitalEntitySet; + boolean autocreateIndex = false; + + public void autocreateIndex(boolean autocreateIndex) { + this.autocreateIndex = autocreateIndex; + } + + public void intitalEntitySet(Set> intitalEntitySet) { + this.intitalEntitySet = intitalEntitySet; + } + + public void intitalEntitySet(Class... initialEntitySet) { + this.intitalEntitySet = new HashSet<>(Arrays.asList(initialEntitySet)); + } + + Set> initialEntitySet() { + return intitalEntitySet != null ? intitalEntitySet : Collections.emptySet(); + } + } + + public static class AuditingConfigurer { + + Function auditingHandlerFunction; + + public void auditingHandler(Function auditingHandlerFunction) { + this.auditingHandlerFunction = auditingHandlerFunction; + } + + IsNewAwareAuditingHandler auditingHandlers(MongoMappingContext mongoMappingContext) { + return auditingHandlerFunction.apply(mongoMappingContext); + } + + boolean hasAuditingHandler() { + return auditingHandlerFunction != null; + } + } + + public static class ApplicationContextConfigurer { + + List>> listeners = new ArrayList<>(); + ApplicationContext applicationContext; + + public void applicationContext(ApplicationContext context) { + this.applicationContext = context; + } + + public void addEventListener(ApplicationListener> listener) { + this.listeners.add(listener); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 77361606d7..1e0e34261b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -47,9 +47,9 @@ public class MongoTestUtils { private static final Environment ENV = new StandardEnvironment(); private static final Duration DEFAULT_TIMEOUT = Duration.ofMillis(10); - public static final String CONNECTION_STRING = "mongodb://127.0.0.1:27017/?replicaSet=rs0&w=majority"; + public static final String CONNECTION_STRING = "mongodb://127.0.0.1:27017/?replicaSet=rs0&w=majority&uuidrepresentation=javaLegacy"; - private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/?w=majority"; + private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/?w=majority&uuidrepresentation=javaLegacy"; private static final Version ANY = new Version(9999, 9999, 9999); @@ -185,6 +185,15 @@ public static void flushCollection(String dbName, String collectionName, .verifyComplete(); } + public static void flushCollection(String dbName, String collectionName, + com.mongodb.client.MongoClient client) { + + com.mongodb.client.MongoDatabase database = client.getDatabase(dbName) + .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); + + database.getCollection(collectionName).deleteMany(new Document()); + } + /** * Create a new {@link com.mongodb.client.MongoClient} with defaults suitable for replica set usage. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java new file mode 100644 index 0000000000..66762b533f --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java @@ -0,0 +1,145 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import com.mongodb.reactivestreams.client.MongoClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.bson.Document; +import org.reactivestreams.Publisher; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; + +/** + * A {@link ReactiveMongoTemplate} with configuration hooks and extension suitable for tests. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ReactiveMongoTestTemplate extends ReactiveMongoTemplate { + + private final MongoTestTemplateConfiguration cfg; + + public ReactiveMongoTestTemplate(MongoClient client, String database, Class... initialEntities) { + this(cfg -> { + cfg.configureDatabaseFactory(it -> { + + it.client(client); + it.defaultDb(database); + }); + + cfg.configureMappingContext(it -> { + + it.autocreateIndex(false); + it.intitalEntitySet(initialEntities); + }); + }); + } + + public ReactiveMongoTestTemplate(Consumer cfg) { + + this(new Supplier() { + @Override + public MongoTestTemplateConfiguration get() { + + MongoTestTemplateConfiguration config = new MongoTestTemplateConfiguration(); + cfg.accept(config); + return config; + } + }); + } + + public ReactiveMongoTestTemplate(Supplier config) { + this(config.get()); + } + + public ReactiveMongoTestTemplate(MongoTestTemplateConfiguration config) { + super(config.reactiveDatabaseFactory(), config.mongoConverter()); + + ApplicationContext applicationContext = config.getApplicationContext(); + if (applicationContext != null) { + setApplicationContext(applicationContext); + } + + this.cfg = config; + } + + public ReactiveMongoDatabaseFactory getDatabaseFactory() { + return cfg.reactiveDatabaseFactory(); + } + + public Mono flush() { + return flush(Flux.fromStream( + PersistentEntities.of(getConverter().getMappingContext()).stream().map(it -> getCollectionName(it.getType())))); + } + + public Mono flushDatabase() { + return flush(getMongoDatabase().listCollectionNames()); + } + + public Mono flush(Class... entities) { + return flush(Flux.fromStream(Arrays.asList(entities).stream().map(this::getCollectionName))); + } + + public Mono flush(String... collections) { + return flush(Flux.fromArray(collections)); + } + + public Mono flush(Publisher collectionNames) { + + return Flux.from(collectionNames) + .flatMap(collection -> Mono.from(getCollection(collection).deleteMany(new Document())).then() + .onErrorResume(it -> Mono.from(getCollection(collection).drop()).then())) + .then(); + } + + public Mono flush(Object... objects) { + + return flush(Flux.fromStream(Arrays.asList(objects).stream().map(it -> { + + if (it instanceof String) { + return (String) it; + } + if (it instanceof Class) { + return getCollectionName((Class) it); + } + return it.toString(); + }))); + } + + public Mono dropDatabase() { + return Mono.from(getMongoDatabase().drop()).then(); + } + + public void dropIndexes(String... collections) { + for (String collection : collections) { + getCollection(collection).dropIndexes(); + } + } + + public void dropIndexes(Class... entities) { + for (Class entity : entities) { + getCollection(getCollectionName(entity)).dropIndexes(); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java new file mode 100644 index 0000000000..89e8f02278 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java @@ -0,0 +1,56 @@ +/* + * Copyright 2020 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 + * + * https://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.test.util; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ExtendWith(MongoTemplateExtension.class) +public @interface Template { + + /** + * @return name of the database to use. Use empty String to generate the database name for the + * {@link ExtensionContext#getTestClass() test class}. + */ + String database() default ""; + + /** + * Pre initilaize the {@link org.springframework.data.mapping.context.MappingContext} with the given entities. + * + * @return empty by default. + */ + Class[] initialEntitySet() default {}; + + /** + * Use a {@link ReplSetClient} if {@literal true}. + * + * @return false by default. + */ + boolean replicaSet() default false; +} From 46ab6b4c945fa5eef1acc000c9d9735a715c8f31 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 6 Mar 2020 11:33:40 +0100 Subject: [PATCH 0093/1381] DATAMONGO-2481 - Polishing. Migrate more tests to JUnit 5. Rearrange methods. Reduce method visibility according to JUnit 5 requirements. Remove Java 11 build and only use Java 8 and 13. Original pull request: #838. --- Jenkinsfile | 36 -- spring-data-mongodb/pom.xml | 6 - .../ConfigClassInDefaultPackageUnitTests.java | 4 +- .../data/mongodb/DependencyTests.java | 12 +- .../mongodb/MongoDatabaseUtilsUnitTests.java | 82 +++-- .../MongoTransactionManagerUnitTests.java | 29 +- .../ReactiveMongoDatabaseUtilsUnitTests.java | 39 +-- ...ctiveMongoTransactionManagerUnitTests.java | 49 +-- ...essionAwareMethodInterceptorUnitTests.java | 13 +- .../AbstractMongoConfigurationUnitTests.java | 3 +- ...ctReactiveMongoConfigurationUnitTests.java | 2 +- .../config/AuditingIntegrationTests.java | 2 +- ...gMongoConverterParserIntegrationTests.java | 2 +- .../MongoAuditingRegistrarUnitTests.java | 16 +- .../MongoClientParserIntegrationTests.java | 6 +- .../MongoDbFactoryParserIntegrationTests.java | 6 +- .../config/MongoParserIntegrationTests.java | 10 +- ...ReadPreferencePropertyEditorUnitTests.java | 6 +- ...tringToWriteConcernConverterUnitTests.java | 2 +- .../WriteConcernPropertyEditorUnitTests.java | 6 +- .../core/ChangeStreamOptionsUnitTests.java | 2 +- ...oseableIterableCursorAdapterUnitTests.java | 51 +-- .../data/mongodb/core/CollationUnitTests.java | 2 +- .../mongodb/core/CountQueryUnitTests.java | 6 +- .../core/DefaultBulkOperationsUnitTests.java | 53 +-- .../core/DefaultIndexOperationsUnitTests.java | 33 +- ...faultReactiveIndexOperationsUnitTests.java | 29 +- .../DefaultScriptOperationsUnitTests.java | 36 +- .../core/EntityOperationUnitTests.java | 7 +- ...eAggregationOperationSupportUnitTests.java | 37 +- ...utableInsertOperationSupportUnitTests.java | 49 +-- ...bleMapReduceOperationSupportUnitTests.java | 38 ++- .../core/GeoCommandStatisticsUnitTests.java | 2 +- ...appingMongoJsonSchemaCreatorUnitTests.java | 6 +- ...ntSettingsFactoryBeanIntegrationTests.java | 2 +- ...ngoClientSettingsFactoryBeanUnitTests.java | 3 +- ...ngoEncryptionSettingsFactoryBeanTests.java | 2 +- .../MongoExceptionTranslatorUnitTests.java | 6 +- .../data/mongodb/core/MongoTemplateTests.java | 3 +- .../core/QueryCursorPreparerUnitTests.java | 35 +- ...eAggregationOperationSupportUnitTests.java | 30 +- ...ChangeStreamOperationSupportUnitTests.java | 32 +- ...activeInsertOperationSupportUnitTests.java | 32 +- ...iveMapReduceOperationSupportUnitTests.java | 41 ++- .../core/ReactiveMongoTemplateIndexTests.java | 20 +- .../core/ReactiveMongoTemplateTests.java | 214 ++++++------ .../core/SerializationUtilsUnitTests.java | 2 +- ...leMongoClientDatabaseFactoryUnitTests.java | 20 +- ...ReactiveMongoDatabaseFactoryUnitTests.java | 14 +- .../aggregation/AggregationOptionsTests.java | 6 +- .../AggregationUpdateUnitTests.java | 2 +- .../aggregation/ArrayOperatorsUnitTests.java | 2 +- .../BucketAutoOperationUnitTests.java | 2 +- .../aggregation/BucketOperationUnitTests.java | 2 +- .../ConvertOperatorsUnitTests.java | 2 +- .../aggregation/CountOperationUnitTests.java | 2 +- .../aggregation/ExposedFieldsUnitTests.java | 2 +- .../core/aggregation/FieldsUnitTests.java | 2 +- .../FilterExpressionUnitTests.java | 25 +- .../GeoNearOperationUnitTests.java | 2 +- .../GraphLookupOperationUnitTests.java | 2 +- .../aggregation/GroupOperationUnitTests.java | 2 +- .../aggregation/LookupOperationUnitTests.java | 2 +- .../aggregation/ObjectOperatorsUnitTests.java | 2 +- .../aggregation/OutOperationUnitTest.java | 2 +- .../ProjectionOperationUnitTests.java | 2 +- .../ReactiveAggregationUnitTests.java | 41 +-- .../ReplaceRootOperationUnitTests.java | 2 +- .../ReplaceWithOperationUnitTests.java | 2 +- .../aggregation/SampleOperationUnitTests.java | 2 +- .../aggregation/SetOperationUnitTests.java | 2 +- .../aggregation/SkipOperationUnitTests.java | 2 +- .../SortByCountOperationUnitTests.java | 2 +- .../aggregation/SortOperationUnitTests.java | 2 +- .../aggregation/StringOperatorsUnitTests.java | 2 +- ...dAggregationOperationContextUnitTests.java | 16 +- .../aggregation/UnsetOperationUnitTests.java | 2 +- .../aggregation/UnwindOperationUnitTests.java | 2 +- .../auditing/MongoTemplateAuditingTests.java | 2 +- .../AbstractMongoConverterUnitTests.java | 2 +- .../convert/CustomConvertersUnitTests.java | 46 ++- .../core/convert/DataMongo273Tests.java | 10 +- .../DbRefMappingMongoConverterUnitTests.java | 12 +- .../DefaultDbRefResolverUnitTests.java | 38 ++- .../DefaultMongoTypeMapperUnitTests.java | 6 +- .../convert/DocumentAccessorUnitTests.java | 2 +- .../core/convert/GeoConvertersUnitTests.java | 2 +- .../convert/GeoJsonConverterUnitTests.java | 2 +- .../LazyLoadingInterceptorUnitTests.java | 8 +- .../MappingMongoConverterUnitTests.java | 320 +++++++++--------- .../convert/MongoConvertersUnitTests.java | 3 +- .../MongoCustomConversionsUnitTests.java | 7 +- .../convert/MongoExampleMapperUnitTests.java | 12 +- .../MongoJsonSchemaMapperUnitTests.java | 6 +- .../NamedMongoScriptConvertsUnitTests.java | 2 +- .../core/convert/ObjectPathUnitTests.java | 6 +- .../TermToStringConverterUnitTests.java | 2 +- .../core/convert/UpdateMapperUnitTests.java | 185 +++++----- .../core/geo/AbstractGeoSpatialTests.java | 2 +- .../core/geo/GeoJsonModuleUnitTests.java | 6 +- .../core/index/IndexFieldUnitTests.java | 2 +- .../core/index/IndexInfoUnitTests.java | 2 +- ...PersistentEntityIndexCreatorUnitTests.java | 56 +-- ...ersistentEntityIndexResolverUnitTests.java | 2 +- ...PersistentEntityIndexCreatorUnitTests.java | 29 +- .../BasicMongoPersistentEntityUnitTests.java | 62 ++-- ...BasicMongoPersistentPropertyUnitTests.java | 6 +- .../core/mapping/GenericMappingTests.java | 26 +- .../mapping/MongoMappingContextUnitTests.java | 42 +-- ...PersistentPropertyComparatorUnitTests.java | 12 +- .../AbstractMongoEventListenerUnitTests.java | 2 +- .../AuditingEntityCallbackUnitTests.java | 34 +- .../event/AuditingEventListenerUnitTests.java | 35 +- .../event/LoggingEventListenerTests.java | 10 +- .../ValidatingMongoEventListenerTests.java | 19 +- .../mapreduce/MapReduceCountsUnitTests.java | 2 +- .../core/mapreduce/MapReduceOptionsTests.java | 2 +- .../mapreduce/MapReduceResultsUnitTests.java | 2 +- .../messaging/ChangeStreamTaskUnitTests.java | 31 +- .../core/messaging/ChangeStreamTests.java | 54 +-- .../messaging/CursorReadingTaskUnitTests.java | 17 +- ...aultMessageListenerContainerUnitTests.java | 41 +-- .../TailableCursorRequestUnitTests.java | 3 +- .../core/messaging/TaskFactoryUnitTests.java | 31 +- .../core/query/BasicQueryUnitTests.java | 2 +- .../mongodb/core/query/FieldUnitTests.java | 2 +- .../mongodb/core/query/IndexUnitTests.java | 2 +- .../core/query/MetricConversionUnitTests.java | 2 +- .../core/query/NearQueryUnitTests.java | 2 +- .../data/mongodb/core/query/SortTests.java | 2 +- .../core/query/TextCriteriaUnitTests.java | 2 +- .../core/query/TextQueryUnitTests.java | 2 +- .../query/UntypedExampleMatcherUnitTests.java | 7 +- .../data/mongodb/core/query/UpdateTests.java | 2 +- .../schema/JsonSchemaObjectUnitTests.java | 2 +- .../schema/JsonSchemaPropertyUnitTests.java | 2 +- .../core/schema/MongoJsonSchemaUnitTests.java | 24 +- .../ExecutableMongoScriptUnitTests.java | 43 +-- .../script/NamedMongoScriptUnitTests.java | 2 +- .../core/spel/ExpressionNodeUnitTests.java | 20 +- .../CriteriaValidatorUnitTests.java | 2 +- .../data/mongodb/gridfs/AntPathUnitTests.java | 2 +- .../gridfs/GridFsResourceUnitTests.java | 2 +- .../mongodb/performance/PerformanceTests.java | 6 +- .../performance/ReactivePerformanceTests.java | 7 +- ...tractPersonRepositoryIntegrationTests.java | 16 +- .../data/mongodb/repository/Contact.java | 4 + .../cdi/CdiExtensionIntegrationTests.java | 10 +- ...sitoryConfigurationExtensionUnitTests.java | 2 +- ...sitoryConfigurationExtensionUnitTests.java | 2 +- .../query/AbstractMongoQueryUnitTests.java | 89 ++--- .../AbstractReactiveMongoQueryUnitTests.java | 57 ++-- .../ConvertingParameterAccessorUnitTests.java | 12 +- ...appingMongoEntityInformationUnitTests.java | 8 +- ...oParametersParameterAccessorUnitTests.java | 2 +- .../query/MongoParametersUnitTests.java | 48 +-- .../query/MongoQueryExecutionUnitTests.java | 58 ++-- .../query/PartTreeMongoQueryUnitTests.java | 12 +- .../ReactiveMongoQueryExecutionUnitTests.java | 8 +- ...activeStringBasedAggregationUnitTests.java | 12 +- ...eactiveStringBasedMongoQueryUnitTests.java | 12 +- .../StringBasedAggregationUnitTests.java | 13 +- .../query/StringBasedMongoQueryUnitTests.java | 13 +- ...nsuringQueryCreationListenerUnitTests.java | 31 +- .../MongoRepositoryFactoryBeanUnitTests.java | 8 +- .../MongoRepositoryFactoryUnitTests.java | 12 +- .../SimpleMongoRepositoryUnitTests.java | 12 +- ...leMongoRepositoryVersionedEntityTests.java | 28 +- ...impleReactiveMongoRepositoryUnitTests.java | 45 +-- ...veMongoRepositoryVersionedEntityTests.java | 4 +- .../SpringDataMongodbSerializerUnitTests.java | 13 +- .../mongodb/test/util/CleanMongoDBTests.java | 38 ++- .../test/util/MongoClientExtension.java | 5 +- .../test/util/MongoTemplateExtension.java | 86 +++-- .../test/util/ReactiveMongoTestTemplate.java | 6 +- .../data/mongodb/test/util/Template.java | 11 +- 176 files changed, 1659 insertions(+), 1634 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d7b972c253..ca8038866a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,22 +46,6 @@ pipeline { } } } - stage('Publish JDK 11 + MongoDB 4.2') { - when { - changeset "ci/openjdk11-mongodb-4.2/**" - } - agent { label 'data' } - options { timeout(time: 30, unit: 'MINUTES') } - - steps { - script { - def image = docker.build("springci/spring-data-openjdk11-with-mongodb-4.2.0", "ci/openjdk11-mongodb-4.2/") - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - image.push() - } - } - } - } stage('Publish JDK 13 + MongoDB 4.2') { when { changeset "ci/openjdk13-mongodb-4.2/**" @@ -155,26 +139,6 @@ pipeline { } } - stage("test: baseline (jdk11)") { - agent { - docker { - image 'springci/spring-data-openjdk11-with-mongodb-4.2.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } - } - options { timeout(time: 30, unit: 'MINUTES') } - steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Duser.name=jenkins -Dsort -U -B' - } - } - stage("test: baseline (jdk13)") { agent { docker { diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 76df2c09ee..872db5d428 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -344,12 +344,6 @@ src/test/resources/logging.properties true - - - listener - org.springframework.data.mongodb.test.util.CleanMongoDBJunitRunListener - - diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java index 48450f1416..2ba51d37ce 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackageUnitTests.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import org.junit.Test; + +import org.junit.jupiter.api.Test; + import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java index d1d92aaca9..166ae90290 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java @@ -16,11 +16,11 @@ package org.springframework.data.mongodb; import static de.schauderhaft.degraph.check.JCheck.*; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.*; import de.schauderhaft.degraph.configuration.NamedPattern; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests package dependency constraints. @@ -28,10 +28,10 @@ * @author Jens Schauder * @author Oliver Gierke */ -public class DependencyTests { +class DependencyTests { @Test - public void noInternalPackageCycles() { + void noInternalPackageCycles() { assertThat(classpath() // .noJars() // @@ -43,7 +43,7 @@ public void noInternalPackageCycles() { } @Test - public void onlyConfigMayUseRepository() { + void onlyConfigMayUseRepository() { assertThat(classpath() // .including("org.springframework.data.**") // @@ -60,7 +60,7 @@ public void onlyConfigMayUseRepository() { } @Test - public void commonsInternaly() { + void commonsInternaly() { assertThat(classpath() // .noJars() // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java index 700b6f6a67..b51468e3fd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java @@ -22,12 +22,11 @@ import javax.transaction.Status; import javax.transaction.UserTransaction; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.jta.JtaTransactionManager; @@ -42,8 +41,8 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class MongoDatabaseUtilsUnitTests { +@ExtendWith(MockitoExtension.class) +class MongoDatabaseUtilsUnitTests { @Mock ClientSession session; @Mock ServerSession serverSession; @@ -52,23 +51,8 @@ public class MongoDatabaseUtilsUnitTests { @Mock UserTransaction userTransaction; - @Before - public void setUp() { - - when(dbFactory.getSession(any())).thenReturn(session); - - when(dbFactory.withSession(session)).thenReturn(dbFactory); - - when(dbFactory.getMongoDatabase()).thenReturn(db); - - when(session.getServerSession()).thenReturn(serverSession); - when(session.hasActiveTransaction()).thenReturn(true); - - when(serverSession.isClosed()).thenReturn(false); - } - - @After - public void verifyTransactionSynchronizationManagerState() { + @AfterEach + void verifyTransactionSynchronizationManagerState() { assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty()).isTrue(); assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isFalse(); @@ -79,7 +63,7 @@ public void verifyTransactionSynchronizationManagerState() { } @Test // DATAMONGO-2130 - public void isTransactionActiveShouldDetectTxViaFactory() { + void isTransactionActiveShouldDetectTxViaFactory() { when(dbFactory.isTransactionActive()).thenReturn(true); @@ -87,7 +71,7 @@ public void isTransactionActiveShouldDetectTxViaFactory() { } @Test // DATAMONGO-2130 - public void isTransactionActiveShouldReturnFalseIfNoTxActive() { + void isTransactionActiveShouldReturnFalseIfNoTxActive() { when(dbFactory.isTransactionActive()).thenReturn(false); @@ -95,7 +79,12 @@ public void isTransactionActiveShouldReturnFalseIfNoTxActive() { } @Test // DATAMONGO-2130 - public void isTransactionActiveShouldLookupTxForActiveTransactionSynchronizationViaTxManager() { + void isTransactionActiveShouldLookupTxForActiveTransactionSynchronizationViaTxManager() { + + when(dbFactory.getSession(any())).thenReturn(session); + when(session.getServerSession()).thenReturn(serverSession); + when(session.hasActiveTransaction()).thenReturn(true); + when(serverSession.isClosed()).thenReturn(false); when(dbFactory.isTransactionActive()).thenReturn(false); @@ -112,7 +101,7 @@ protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) } @Test // DATAMONGO-1920 - public void shouldNotStartSessionWhenNoTransactionOngoing() { + void shouldNotStartSessionWhenNoTransactionOngoing() { MongoDatabaseUtils.getDatabase(dbFactory, SessionSynchronization.ON_ACTUAL_TRANSACTION); @@ -121,7 +110,14 @@ public void shouldNotStartSessionWhenNoTransactionOngoing() { } @Test // DATAMONGO-1920 - public void shouldParticipateInOngoingJtaTransactionWithCommitWhenSessionSychronizationIsAny() throws Exception { + void shouldParticipateInOngoingJtaTransactionWithCommitWhenSessionSychronizationIsAny() throws Exception { + + when(dbFactory.getSession(any())).thenReturn(session); + when(dbFactory.withSession(session)).thenReturn(dbFactory); + when(dbFactory.getMongoDatabase()).thenReturn(db); + when(session.getServerSession()).thenReturn(serverSession); + when(session.hasActiveTransaction()).thenReturn(true); + when(serverSession.isClosed()).thenReturn(false); when(userTransaction.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION, Status.STATUS_ACTIVE, Status.STATUS_ACTIVE); @@ -152,7 +148,14 @@ protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) } @Test // DATAMONGO-1920 - public void shouldParticipateInOngoingJtaTransactionWithRollbackWhenSessionSychronizationIsAny() throws Exception { + void shouldParticipateInOngoingJtaTransactionWithRollbackWhenSessionSychronizationIsAny() throws Exception { + + when(dbFactory.getSession(any())).thenReturn(session); + when(dbFactory.withSession(session)).thenReturn(dbFactory); + when(dbFactory.getMongoDatabase()).thenReturn(db); + when(session.getServerSession()).thenReturn(serverSession); + when(session.hasActiveTransaction()).thenReturn(true); + when(serverSession.isClosed()).thenReturn(false); when(userTransaction.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION, Status.STATUS_ACTIVE, Status.STATUS_ACTIVE); @@ -185,8 +188,7 @@ protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) } @Test // DATAMONGO-1920 - public void shouldNotParticipateInOngoingJtaTransactionWithRollbackWhenSessionSychronizationIsNative() - throws Exception { + void shouldNotParticipateInOngoingJtaTransactionWithRollbackWhenSessionSychronizationIsNative() throws Exception { when(userTransaction.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION, Status.STATUS_ACTIVE, Status.STATUS_ACTIVE); @@ -219,7 +221,13 @@ protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) } @Test // DATAMONGO-1920 - public void shouldParticipateInOngoingMongoTransactionWhenSessionSychronizationIsNative() { + void shouldParticipateInOngoingMongoTransactionWhenSessionSychronizationIsNative() { + + when(dbFactory.getSession(any())).thenReturn(session); + when(dbFactory.withSession(session)).thenReturn(dbFactory); + when(dbFactory.getMongoDatabase()).thenReturn(db); + when(session.getServerSession()).thenReturn(serverSession); + when(serverSession.isClosed()).thenReturn(false); MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionTemplate txTemplate = new TransactionTemplate(txManager); @@ -245,7 +253,13 @@ protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) } @Test // DATAMONGO-1920 - public void shouldParticipateInOngoingMongoTransactionWhenSessionSychronizationIsAny() { + void shouldParticipateInOngoingMongoTransactionWhenSessionSynchronizationIsAny() { + + when(dbFactory.getSession(any())).thenReturn(session); + when(dbFactory.withSession(session)).thenReturn(dbFactory); + when(dbFactory.getMongoDatabase()).thenReturn(db); + when(session.getServerSession()).thenReturn(serverSession); + when(serverSession.isClosed()).thenReturn(false); MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionTemplate txTemplate = new TransactionTemplate(txManager); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java index e391866ae7..338d35adaf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java @@ -18,12 +18,12 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.transaction.TransactionDefinition; @@ -41,7 +41,7 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MongoTransactionManagerUnitTests { @Mock ClientSession session; @@ -52,24 +52,16 @@ public class MongoTransactionManagerUnitTests { @Mock MongoDatabase db; @Mock MongoDatabase db2; - @Before + @BeforeEach public void setUp() { when(dbFactory.getSession(any())).thenReturn(session, session2); - when(dbFactory.withSession(session)).thenReturn(dbFactory); - when(dbFactory.withSession(session2)).thenReturn(dbFactory2); - when(dbFactory.getMongoDatabase()).thenReturn(db); - when(dbFactory2.getMongoDatabase()).thenReturn(db2); - when(session.getServerSession()).thenReturn(serverSession); - when(session2.getServerSession()).thenReturn(serverSession); - - when(serverSession.isClosed()).thenReturn(false); } - @After + @AfterEach public void verifyTransactionSynchronizationManager() { assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty()).isTrue(); @@ -238,6 +230,11 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { @Test // DATAMONGO-1920 public void suspendTransactionWhilePropagationRequiresNew() { + when(dbFactory.withSession(session2)).thenReturn(dbFactory2); + when(dbFactory2.getMongoDatabase()).thenReturn(db2); + when(session2.getServerSession()).thenReturn(serverSession); + when(serverSession.isClosed()).thenReturn(false); + MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionStatus txStatus = txManager.getTransaction(new DefaultTransactionDefinition()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java index 9a46ff82af..f05e1c6769 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java @@ -22,11 +22,10 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.transaction.reactive.TransactionSynchronizationManager; import org.springframework.transaction.reactive.TransactionalOperator; @@ -42,26 +41,16 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class ReactiveMongoDatabaseUtilsUnitTests { +@ExtendWith(MockitoExtension.class) +class ReactiveMongoDatabaseUtilsUnitTests { @Mock ClientSession session; @Mock ServerSession serverSession; @Mock ReactiveMongoDatabaseFactory databaseFactory; @Mock MongoDatabase db; - @Before - public void setUp() { - - when(databaseFactory.getSession(any())).thenReturn(Mono.just(session)); - when(databaseFactory.getMongoDatabase()).thenReturn(db); - - when(session.getServerSession()).thenReturn(serverSession); - when(session.hasActiveTransaction()).thenReturn(true); - } - @Test // DATAMONGO-2265 - public void isTransactionActiveShouldDetectTxViaFactory() { + void isTransactionActiveShouldDetectTxViaFactory() { when(databaseFactory.isTransactionActive()).thenReturn(true); @@ -71,7 +60,7 @@ public void isTransactionActiveShouldDetectTxViaFactory() { } @Test // DATAMONGO-2265 - public void isTransactionActiveShouldReturnFalseIfNoTxActive() { + void isTransactionActiveShouldReturnFalseIfNoTxActive() { when(databaseFactory.isTransactionActive()).thenReturn(false); @@ -81,8 +70,11 @@ public void isTransactionActiveShouldReturnFalseIfNoTxActive() { } @Test // DATAMONGO-2265 - public void isTransactionActiveShouldLookupTxForActiveTransactionSynchronizationViaTxManager() { + void isTransactionActiveShouldLookupTxForActiveTransactionSynchronizationViaTxManager() { + when(session.getServerSession()).thenReturn(serverSession); + when(session.hasActiveTransaction()).thenReturn(true); + when(databaseFactory.getSession(any())).thenReturn(Mono.just(session)); when(databaseFactory.isTransactionActive()).thenReturn(false); when(session.commitTransaction()).thenReturn(Mono.empty()); @@ -96,7 +88,9 @@ public void isTransactionActiveShouldLookupTxForActiveTransactionSynchronization } @Test // DATAMONGO-2265 - public void shouldNotStartSessionWhenNoTransactionOngoing() { + void shouldNotStartSessionWhenNoTransactionOngoing() { + + when(databaseFactory.getMongoDatabase()).thenReturn(db); ReactiveMongoDatabaseUtils.getDatabase(databaseFactory, SessionSynchronization.ON_ACTUAL_TRANSACTION) // .as(StepVerifier::create) // @@ -108,7 +102,10 @@ public void shouldNotStartSessionWhenNoTransactionOngoing() { } @Test // DATAMONGO-2265 - public void shouldParticipateInOngoingMongoTransactionWhenSessionSychronizationIsNative() { + void shouldParticipateInOngoingMongoTransactionWhenSessionSychronizationIsNative() { + + when(session.getServerSession()).thenReturn(serverSession); + when(databaseFactory.getSession(any())).thenReturn(Mono.just(session)); ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); when(session.abortTransaction()).thenReturn(Mono.empty()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java index a0feccb797..d04db25297 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java @@ -15,24 +15,21 @@ */ package org.springframework.data.mongodb; -import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.reactive.TransactionalOperator; import org.springframework.transaction.support.DefaultTransactionDefinition; -import org.springframework.transaction.support.TransactionSynchronizationManager; import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.MongoDatabase; @@ -44,8 +41,8 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class ReactiveMongoTransactionManagerUnitTests { +@ExtendWith(MockitoExtension.class) +class ReactiveMongoTransactionManagerUnitTests { @Mock ClientSession session; @Mock ClientSession session2; @@ -55,30 +52,16 @@ public class ReactiveMongoTransactionManagerUnitTests { @Mock MongoDatabase db; @Mock MongoDatabase db2; - @Before - public void setUp() { - + @BeforeEach + void setUp() { when(databaseFactory.getSession(any())).thenReturn(Mono.just(session), Mono.just(session2)); - when(databaseFactory.withSession(session)).thenReturn(databaseFactory); - when(databaseFactory.withSession(session2)).thenReturn(databaseFactory2); - when(databaseFactory.getMongoDatabase()).thenReturn(db); - when(databaseFactory2.getMongoDatabase()).thenReturn(db2); - when(session.getServerSession()).thenReturn(serverSession); - when(session2.getServerSession()).thenReturn(serverSession); - } - - @After - public void verifyTransactionSynchronizationManager() { - - assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty()).isTrue(); - assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isFalse(); } @Test // DATAMONGO-2265 - public void triggerCommitCorrectly() { + void triggerCommitCorrectly() { ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(databaseFactory); @@ -103,7 +86,7 @@ public void triggerCommitCorrectly() { } @Test // DATAMONGO-2265 - public void participateInOnGoingTransactionWithCommit() { + void participateInOnGoingTransactionWithCommit() { ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(databaseFactory); @@ -131,7 +114,7 @@ public void participateInOnGoingTransactionWithCommit() { } @Test // DATAMONGO-2265 - public void participateInOnGoingTransactionWithRollbackOnly() { + void participateInOnGoingTransactionWithRollbackOnly() { ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(databaseFactory); @@ -156,7 +139,7 @@ public void participateInOnGoingTransactionWithRollbackOnly() { } @Test // DATAMONGO-2265 - public void suspendTransactionWhilePropagationNotSupported() { + void suspendTransactionWhilePropagationNotSupported() { ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(databaseFactory); @@ -195,7 +178,11 @@ public void suspendTransactionWhilePropagationNotSupported() { } @Test // DATAMONGO-2265 - public void suspendTransactionWhilePropagationRequiresNew() { + void suspendTransactionWhilePropagationRequiresNew() { + + when(databaseFactory.withSession(session2)).thenReturn(databaseFactory2); + when(databaseFactory2.getMongoDatabase()).thenReturn(db2); + when(session2.getServerSession()).thenReturn(serverSession); ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(databaseFactory); @@ -237,7 +224,7 @@ public void suspendTransactionWhilePropagationRequiresNew() { } @Test // DATAMONGO-2265 - public void readonlyShouldInitiateASessionStartAndCommitTransaction() { + void readonlyShouldInitiateASessionStartAndCommitTransaction() { ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); ReactiveMongoTemplate template = new ReactiveMongoTemplate(databaseFactory); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java index 85711d8344..e27eb7de5c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/SessionAwareMethodInterceptorUnitTests.java @@ -24,11 +24,12 @@ import java.lang.reflect.Proxy; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.data.mongodb.SessionAwareMethodInterceptor.MethodCache; import org.springframework.test.util.ReflectionTestUtils; @@ -44,7 +45,7 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class SessionAwareMethodInterceptorUnitTests { @Mock ClientSession session; @@ -54,7 +55,7 @@ public class SessionAwareMethodInterceptorUnitTests { MongoCollection collection; MongoDatabase database; - @Before + @BeforeEach public void setUp() { collection = createProxyInstance(session, targetCollection, MongoCollection.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index 50debf50b9..d51b6d234b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -25,7 +25,8 @@ import java.util.Collections; import java.util.Set; -import org.junit.Test; +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java index 6cef594d69..a89bdd2993 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java @@ -25,7 +25,7 @@ import java.util.Collections; import java.util.Set; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java index 14712ebcfd..d97d97daee 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.joda.time.DateTime; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java index 5518190509..df7080bed3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java @@ -21,7 +21,7 @@ import java.util.Set; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanReference; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java index b4cdc51f9d..2022648957 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoAuditingRegistrarUnitTests.java @@ -17,10 +17,10 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.core.type.AnnotationMetadata; @@ -30,21 +30,21 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class MongoAuditingRegistrarUnitTests { +@ExtendWith(MockitoExtension.class) +class MongoAuditingRegistrarUnitTests { - MongoAuditingRegistrar registrar = new MongoAuditingRegistrar(); + private MongoAuditingRegistrar registrar = new MongoAuditingRegistrar(); @Mock AnnotationMetadata metadata; @Mock BeanDefinitionRegistry registry; @Test // DATAMONGO-792 - public void rejectsNullAnnotationMetadata() { + void rejectsNullAnnotationMetadata() { assertThatIllegalArgumentException().isThrownBy(() -> registrar.registerBeanDefinitions(null, registry)); } @Test // DATAMONGO-792 - public void rejectsNullBeanDefinitionRegistry() { + void rejectsNullBeanDefinitionRegistry() { assertThatIllegalArgumentException().isThrownBy(() -> registrar.registerBeanDefinitions(metadata, null)); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java index 62a89ef085..e76740e239 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java @@ -19,8 +19,8 @@ import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; @@ -47,7 +47,7 @@ public class MongoClientParserIntegrationTests { DefaultListableBeanFactory factory; BeanDefinitionReader reader; - @Before + @BeforeEach public void setUp() { this.factory = new DefaultListableBeanFactory(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 51c8aefd65..129eafc927 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -17,8 +17,8 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConstructorArgumentValues; @@ -51,7 +51,7 @@ public class MongoDbFactoryParserIntegrationTests { DefaultListableBeanFactory factory; BeanDefinitionReader reader; - @Before + @BeforeEach public void setUp() { factory = new DefaultListableBeanFactory(); reader = new XmlBeanDefinitionReader(factory); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java index f37eb7ebd1..b030622a59 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java @@ -19,9 +19,9 @@ import java.util.List; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; @@ -44,7 +44,7 @@ public class MongoParserIntegrationTests { DefaultListableBeanFactory factory; BeanDefinitionReader reader; - @Before + @BeforeEach public void setUp() { this.factory = new DefaultListableBeanFactory(); @@ -52,7 +52,7 @@ public void setUp() { } @Test - @Ignore + @Disabled public void readsMongoAttributesCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-bean.xml")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java index 3053e955c6..3aed67e9e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditorUnitTests.java @@ -17,8 +17,8 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import com.mongodb.ReadPreference; @@ -31,7 +31,7 @@ public class ReadPreferencePropertyEditorUnitTests { ReadPreferencePropertyEditor editor; - @Before + @BeforeEach public void setUp() { editor = new ReadPreferencePropertyEditor(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java index ade0f678a1..5842fd1478 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/StringToWriteConcernConverterUnitTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.mongodb.WriteConcern; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java index ad937d3d39..4823398040 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditorUnitTests.java @@ -17,8 +17,8 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import com.mongodb.WriteConcern; @@ -32,7 +32,7 @@ public class WriteConcernPropertyEditorUnitTests { WriteConcernPropertyEditor editor; - @Before + @BeforeEach public void setUp() { editor = new WriteConcernPropertyEditor(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java index 2f03056ce7..635951448d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ChangeStreamOptionsUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.BsonDocument; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link ChangeStreamOptions}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java index 4db0adf31a..37417f1c5a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CloseableIterableCursorAdapterUnitTests.java @@ -15,14 +15,16 @@ */ package org.springframework.data.mongodb.core; +import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.core.MongoTemplate.CloseableIterableCursorAdapter; import org.springframework.data.mongodb.core.MongoTemplate.DocumentCallback; @@ -35,40 +37,39 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class CloseableIterableCursorAdapterUnitTests { +@ExtendWith(MockitoExtension.class) +class CloseableIterableCursorAdapterUnitTests { @Mock PersistenceExceptionTranslator exceptionTranslator; @Mock DocumentCallback callback; - MongoCursor cursor; - CloseableIterator adapter; - - @Before - public void setUp() { + private MongoCursor cursor; + private CloseableIterator adapter; - this.cursor = doThrow(IllegalArgumentException.class).when(mock(MongoCursor.class)); - this.adapter = new CloseableIterableCursorAdapter(cursor, exceptionTranslator, callback); + @BeforeEach + void setUp() { + this.cursor = mock(MongoCursor.class); + this.adapter = new CloseableIterableCursorAdapter<>(cursor, exceptionTranslator, callback); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-1276 - public void propagatesOriginalExceptionFromAdapterDotNext() { + @Test // DATAMONGO-1276 + void propagatesOriginalExceptionFromAdapterDotNext() { - cursor.next(); - adapter.next(); + doThrow(IllegalArgumentException.class).when(cursor).next(); + assertThatIllegalArgumentException().isThrownBy(() -> adapter.next()); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-1276 - public void propagatesOriginalExceptionFromAdapterDotHasNext() { + @Test // DATAMONGO-1276 + void propagatesOriginalExceptionFromAdapterDotHasNext() { - cursor.hasNext(); - adapter.hasNext(); + doThrow(IllegalArgumentException.class).when(cursor).hasNext(); + assertThatIllegalArgumentException().isThrownBy(() -> adapter.hasNext()); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-1276 - public void propagatesOriginalExceptionFromAdapterDotClose() { + @Test // DATAMONGO-1276 + void propagatesOriginalExceptionFromAdapterDotClose() { - cursor.close(); - adapter.close(); + doThrow(IllegalArgumentException.class).when(cursor).close(); + assertThatIllegalArgumentException().isThrownBy(() -> adapter.close()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java index 3161608576..9179f829ce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollationUnitTests.java @@ -20,7 +20,7 @@ import java.util.Locale; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation.Alternate; import org.springframework.data.mongodb.core.query.Collation.CaseFirst; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java index 58b8e368f4..054ba26785 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java @@ -20,8 +20,8 @@ import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.test.util.Assertions.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -47,7 +47,7 @@ public class CountQueryUnitTests { MongoDatabaseFactory factory = mock(MongoDatabaseFactory.class); - @Before + @BeforeEach public void setUp() { this.context = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 8034447cc5..98fc767f0f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -30,14 +30,15 @@ import org.bson.BsonDocument; import org.bson.BsonString; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.context.ApplicationEventPublisher; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -83,22 +84,22 @@ * @author Minsu Kim * @author Jens Schauder */ -@RunWith(MockitoJUnitRunner.class) -public class DefaultBulkOperationsUnitTests { +@ExtendWith(MockitoExtension.class) +class DefaultBulkOperationsUnitTests { - MongoTemplate template; + private MongoTemplate template; @Mock MongoDatabase database; @Mock(answer = Answers.RETURNS_DEEP_STUBS) MongoCollection collection; @Mock MongoDatabaseFactory factory; @Mock DbRefResolver dbRefResolver; @Captor ArgumentCaptor>> captor; - MongoConverter converter; - MongoMappingContext mappingContext; + private MongoConverter converter; + private MongoMappingContext mappingContext; - DefaultBulkOperations ops; + private DefaultBulkOperations ops; - @Before - public void setUp() { + @BeforeEach + void setUp() { when(factory.getMongoDatabase()).thenReturn(database); when(factory.getExceptionTranslator()).thenReturn(new NullExceptionTranslator()); @@ -117,7 +118,7 @@ public void setUp() { } @Test // DATAMONGO-1518 - public void updateOneShouldUseCollationWhenPresent() { + void updateOneShouldUseCollationWhenPresent() { ops.updateOne(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen")) .execute(); @@ -130,7 +131,7 @@ public void updateOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void updateManyShouldUseCollationWhenPresent() { + void updateManyShouldUseCollationWhenPresent() { ops.updateMulti(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen")) .execute(); @@ -143,7 +144,7 @@ public void updateManyShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void removeShouldUseCollationWhenPresent() { + void removeShouldUseCollationWhenPresent() { ops.remove(new BasicQuery("{}").collation(Collation.of("de"))).execute(); @@ -155,7 +156,7 @@ public void removeShouldUseCollationWhenPresent() { } @Test // DATAMONGO-2218 - public void replaceOneShouldUseCollationWhenPresent() { + void replaceOneShouldUseCollationWhenPresent() { ops.replaceOne(new BasicQuery("{}").collation(Collation.of("de")), new SomeDomainType()).execute(); @@ -167,7 +168,7 @@ public void replaceOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1678 - public void bulkUpdateShouldMapQueryAndUpdateCorrectly() { + void bulkUpdateShouldMapQueryAndUpdateCorrectly() { ops.updateOne(query(where("firstName").is("danerys")), Update.update("firstName", "queen danerys")).execute(); @@ -179,7 +180,7 @@ public void bulkUpdateShouldMapQueryAndUpdateCorrectly() { } @Test // DATAMONGO-1678 - public void bulkRemoveShouldMapQueryCorrectly() { + void bulkRemoveShouldMapQueryCorrectly() { ops.remove(query(where("firstName").is("danerys"))).execute(); @@ -190,7 +191,7 @@ public void bulkRemoveShouldMapQueryCorrectly() { } @Test // DATAMONGO-2218 - public void bulkReplaceOneShouldMapQueryCorrectly() { + void bulkReplaceOneShouldMapQueryCorrectly() { SomeDomainType replacement = new SomeDomainType(); replacement.firstName = "Minsu"; @@ -207,7 +208,7 @@ public void bulkReplaceOneShouldMapQueryCorrectly() { } @Test // DATAMONGO-2261 - public void bulkInsertInvokesEntityCallbacks() { + void bulkInsertInvokesEntityCallbacks() { BeforeConvertPersonCallback beforeConvertCallback = spy(new BeforeConvertPersonCallback()); BeforeSavePersonCallback beforeSaveCallback = spy(new BeforeSavePersonCallback()); @@ -235,7 +236,7 @@ public void bulkInsertInvokesEntityCallbacks() { } @Test // DATAMONGO-2290 - public void bulkReplaceOneEmitsEventsCorrectly() { + void bulkReplaceOneEmitsEventsCorrectly() { ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); @@ -256,7 +257,7 @@ public void bulkReplaceOneEmitsEventsCorrectly() { } @Test // DATAMONGO-2290 - public void bulkInsertEmitsEventsCorrectly() { + void bulkInsertEmitsEventsCorrectly() { ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); @@ -277,7 +278,7 @@ public void bulkInsertEmitsEventsCorrectly() { } @Test // DATAMONGO-2290 - public void noAfterSaveEventOnFailure() { + void noAfterSaveEventOnFailure() { ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); when(collection.bulkWrite(anyList(), any())).thenThrow(new MongoWriteException( @@ -302,7 +303,7 @@ public void noAfterSaveEventOnFailure() { } @Test // DATAMONGO-2330 - public void writeConcernNotAppliedWhenNotSet() { + void writeConcernNotAppliedWhenNotSet() { ops.updateOne(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen")) .execute(); @@ -311,7 +312,7 @@ public void writeConcernNotAppliedWhenNotSet() { } @Test // DATAMONGO-2330 - public void writeConcernAppliedCorrectlyWhenSet() { + void writeConcernAppliedCorrectlyWhenSet() { ops.setDefaultWriteConcern(WriteConcern.MAJORITY); @@ -322,7 +323,7 @@ public void writeConcernAppliedCorrectlyWhenSet() { } @Test // DATAMONGO-2450 - public void appliesArrayFilterWhenPresent() { + void appliesArrayFilterWhenPresent() { ops.updateOne(new BasicQuery("{}"), new Update().filterArray(Criteria.where("element").gte(100))).execute(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java index 7d7c8ff8f1..ad5d68daba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java @@ -21,12 +21,13 @@ import lombok.Data; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; @@ -46,21 +47,21 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class DefaultIndexOperationsUnitTests { - MongoTemplate template; + private MongoTemplate template; @Mock MongoDatabaseFactory factory; @Mock MongoDatabase db; @Mock MongoCollection collection; - MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); - MappingMongoConverter converter; - MongoMappingContext mappingContext; + private MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; - @Before - public void setUp() { + @BeforeEach + void setUp() { when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); @@ -73,7 +74,7 @@ public void setUp() { } @Test // DATAMONGO-1183 - public void indexOperationsMapFieldNameCorrectly() { + void indexOperationsMapFieldNameCorrectly() { indexOpsFor(Jedi.class).ensureIndex(new Index("name", Direction.DESC)); @@ -81,7 +82,7 @@ public void indexOperationsMapFieldNameCorrectly() { } @Test // DATAMONGO-1854 - public void ensureIndexDoesNotSetCollectionIfNoDefaultDefined() { + void ensureIndexDoesNotSetCollectionIfNoDefaultDefined() { indexOpsFor(Jedi.class).ensureIndex(new Index("firstname", Direction.DESC)); @@ -92,7 +93,7 @@ public void ensureIndexDoesNotSetCollectionIfNoDefaultDefined() { } @Test // DATAMONGO-1854 - public void ensureIndexUsesDefaultCollationIfNoneDefinedInOptions() { + void ensureIndexUsesDefaultCollationIfNoneDefinedInOptions() { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC)); @@ -104,7 +105,7 @@ public void ensureIndexUsesDefaultCollationIfNoneDefinedInOptions() { } @Test // DATAMONGO-1854 - public void ensureIndexDoesNotUseDefaultCollationIfExplicitlySpecifiedInTheIndex() { + void ensureIndexDoesNotUseDefaultCollationIfExplicitlySpecifiedInTheIndex() { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC).collation(Collation.of("en_US"))); @@ -116,7 +117,7 @@ public void ensureIndexDoesNotUseDefaultCollationIfExplicitlySpecifiedInTheIndex } @Test // DATAMONGO-1183 - public void shouldCreateHashedIndexCorrectly() { + void shouldCreateHashedIndexCorrectly() { indexOpsFor(Jedi.class).ensureIndex(HashedIndex.hashed("name")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java index 7659f495f0..2121f6f305 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java @@ -21,13 +21,14 @@ import lombok.Data; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.reactivestreams.Publisher; + import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -45,22 +46,22 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class DefaultReactiveIndexOperationsUnitTests { - ReactiveMongoTemplate template; + private ReactiveMongoTemplate template; @Mock ReactiveMongoDatabaseFactory factory; @Mock MongoDatabase db; @Mock MongoCollection collection; @Mock Publisher publisher; - MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); - MappingMongoConverter converter; - MongoMappingContext mappingContext; + private MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; - @Before - public void setUp() { + @BeforeEach + void setUp() { when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); @@ -73,7 +74,7 @@ public void setUp() { } @Test // DATAMONGO-1854 - public void ensureIndexDoesNotSetCollectionIfNoDefaultDefined() { + void ensureIndexDoesNotSetCollectionIfNoDefaultDefined() { indexOpsFor(Jedi.class).ensureIndex(new Index("firstname", Direction.DESC)).subscribe(); @@ -84,7 +85,7 @@ public void ensureIndexDoesNotSetCollectionIfNoDefaultDefined() { } @Test // DATAMONGO-1854 - public void ensureIndexUsesDefaultCollationIfNoneDefinedInOptions() { + void ensureIndexUsesDefaultCollationIfNoneDefinedInOptions() { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC)).subscribe(); @@ -96,7 +97,7 @@ public void ensureIndexUsesDefaultCollationIfNoneDefinedInOptions() { } @Test // DATAMONGO-1854 - public void ensureIndexDoesNotUseDefaultCollationIfExplicitlySpecifiedInTheIndex() { + void ensureIndexDoesNotUseDefaultCollationIfExplicitlySpecifiedInTheIndex() { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC).collation(Collation.of("en_US"))) .subscribe(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java index 0bac222ec1..13e49494a9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultScriptOperationsUnitTests.java @@ -18,12 +18,12 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.script.ExecutableMongoScript; import org.springframework.data.mongodb.core.script.NamedMongoScript; @@ -35,29 +35,29 @@ * @author Oliver Gierke * @since 1.7 */ -@RunWith(MockitoJUnitRunner.class) -public class DefaultScriptOperationsUnitTests { +@ExtendWith(MockitoExtension.class) +class DefaultScriptOperationsUnitTests { - DefaultScriptOperations scriptOps; + private DefaultScriptOperations scriptOps; @Mock MongoOperations mongoOperations; - @Before - public void setUp() { + @BeforeEach + void setUp() { this.scriptOps = new DefaultScriptOperations(mongoOperations); } @Test // DATAMONGO-479 - public void rejectsNullExecutableMongoScript() { + void rejectsNullExecutableMongoScript() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.register((ExecutableMongoScript) null)); } @Test // DATAMONGO-479 - public void rejectsNullNamedMongoScript() { + void rejectsNullNamedMongoScript() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.register((NamedMongoScript) null)); } @Test // DATAMONGO-479 - public void saveShouldUseCorrectCollectionName() { + void saveShouldUseCorrectCollectionName() { scriptOps.register(new NamedMongoScript("foo", "function...")); @@ -65,7 +65,7 @@ public void saveShouldUseCorrectCollectionName() { } @Test // DATAMONGO-479 - public void saveShouldGenerateScriptNameForExecutableMongoScripts() { + void saveShouldGenerateScriptNameForExecutableMongoScripts() { scriptOps.register(new ExecutableMongoScript("function...")); @@ -76,27 +76,27 @@ public void saveShouldGenerateScriptNameForExecutableMongoScripts() { } @Test // DATAMONGO-479 - public void executeShouldThrowExceptionWhenScriptIsNull() { + void executeShouldThrowExceptionWhenScriptIsNull() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.execute(null)); } @Test // DATAMONGO-479 - public void existsShouldThrowExceptionWhenScriptNameIsNull() { + void existsShouldThrowExceptionWhenScriptNameIsNull() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.exists(null)); } @Test // DATAMONGO-479 - public void existsShouldThrowExceptionWhenScriptNameIsEmpty() { + void existsShouldThrowExceptionWhenScriptNameIsEmpty() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.exists("")); } @Test // DATAMONGO-479 - public void callShouldThrowExceptionWhenScriptNameIsNull() { + void callShouldThrowExceptionWhenScriptNameIsNull() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.call(null)); } @Test // DATAMONGO-479 - public void callShouldThrowExceptionWhenScriptNameIsEmpty() { + void callShouldThrowExceptionWhenScriptNameIsEmpty() { assertThatIllegalArgumentException().isThrownBy(() -> scriptOps.call("")); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java index 23bf06549f..b7680e4345 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationUnitTests.java @@ -17,8 +17,9 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.annotation.Id; @@ -34,7 +35,7 @@ public class EntityOperationUnitTests { MongoMappingContext mappingContext = new MongoMappingContext(); ConversionService conversionService = new DefaultConversionService(); - @Before + @BeforeEach public void setUp() { ops = new EntityOperations(mappingContext); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java index 34fa6a6da4..90decac3a2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupportUnitTests.java @@ -20,12 +20,13 @@ import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.mongodb.core.aggregation.Aggregation; /** @@ -33,40 +34,40 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ExecutableAggregationOperationSupportUnitTests { @Mock MongoTemplate template; - ExecutableAggregationOperationSupport opSupport; + private ExecutableAggregationOperationSupport opSupport; - @Before - public void setUp() { + @BeforeEach + void setUp() { opSupport = new ExecutableAggregationOperationSupport(template); } @Test // DATAMONGO-1563 - public void throwsExceptionOnNullDomainType() { + void throwsExceptionOnNullDomainType() { assertThatIllegalArgumentException().isThrownBy(() -> opSupport.aggregateAndReturn(null)); } @Test // DATAMONGO-1563 - public void throwsExceptionOnNullCollectionWhenUsed() { + void throwsExceptionOnNullCollectionWhenUsed() { assertThatIllegalArgumentException() .isThrownBy(() -> opSupport.aggregateAndReturn(Person.class).inCollection(null)); } @Test // DATAMONGO-1563 - public void throwsExceptionOnEmptyCollectionWhenUsed() { + void throwsExceptionOnEmptyCollectionWhenUsed() { assertThatIllegalArgumentException().isThrownBy(() -> opSupport.aggregateAndReturn(Person.class).inCollection("")); } @Test // DATAMONGO-1563 - public void throwsExceptionOnNullAggregation() { + void throwsExceptionOnNullAggregation() { assertThatIllegalArgumentException().isThrownBy(() -> opSupport.aggregateAndReturn(Person.class).by(null)); } @Test // DATAMONGO-1563 - public void aggregateWithUntypedAggregationAndExplicitCollection() { + void aggregateWithUntypedAggregationAndExplicitCollection() { opSupport.aggregateAndReturn(Person.class).inCollection("star-wars").by(newAggregation(project("foo"))).all(); @@ -76,7 +77,7 @@ public void aggregateWithUntypedAggregationAndExplicitCollection() { } @Test // DATAMONGO-1563 - public void aggregateWithUntypedAggregation() { + void aggregateWithUntypedAggregation() { when(template.getCollectionName(any(Class.class))).thenReturn("person"); @@ -91,7 +92,7 @@ public void aggregateWithUntypedAggregation() { } @Test // DATAMONGO-1563 - public void aggregateWithTypeAggregation() { + void aggregateWithTypeAggregation() { when(template.getCollectionName(any(Class.class))).thenReturn("person"); @@ -106,7 +107,7 @@ public void aggregateWithTypeAggregation() { } @Test // DATAMONGO-1563 - public void aggregateStreamWithUntypedAggregationAndExplicitCollection() { + void aggregateStreamWithUntypedAggregationAndExplicitCollection() { opSupport.aggregateAndReturn(Person.class).inCollection("star-wars").by(newAggregation(project("foo"))).stream(); @@ -116,7 +117,7 @@ public void aggregateStreamWithUntypedAggregationAndExplicitCollection() { } @Test // DATAMONGO-1563 - public void aggregateStreamWithUntypedAggregation() { + void aggregateStreamWithUntypedAggregation() { when(template.getCollectionName(any(Class.class))).thenReturn("person"); @@ -131,7 +132,7 @@ public void aggregateStreamWithUntypedAggregation() { } @Test // DATAMONGO-1563 - public void aggregateStreamWithTypeAggregation() { + void aggregateStreamWithTypeAggregation() { when(template.getCollectionName(any(Class.class))).thenReturn("person"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java index dfe871d13c..90b1d758a8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupportUnitTests.java @@ -23,12 +23,13 @@ import java.util.Arrays; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; @@ -38,7 +39,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ExecutableInsertOperationSupportUnitTests { private static final String STAR_WARS = "star-wars"; @@ -46,16 +47,12 @@ public class ExecutableInsertOperationSupportUnitTests { @Mock MongoTemplate template; @Mock BulkOperations bulkOperations; - ExecutableInsertOperationSupport ops; - - Person luke, han; + private ExecutableInsertOperationSupport ops; - @Before - public void setUp() { + private Person luke, han; - when(template.bulkOps(any(), any(), any())).thenReturn(bulkOperations); - when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); - when(bulkOperations.insert(anyList())).thenReturn(bulkOperations); + @BeforeEach + void setUp() { ops = new ExecutableInsertOperationSupport(template); @@ -69,17 +66,19 @@ public void setUp() { } @Test // DATAMONGO-1563 - public void nullCollectionShouldThrowException() { + void nullCollectionShouldThrowException() { assertThatIllegalArgumentException().isThrownBy(() -> ops.insert(Person.class).inCollection(null)); } @Test // DATAMONGO-1563 - public void nullBulkModeShouldThrowException() { + void nullBulkModeShouldThrowException() { assertThatIllegalArgumentException().isThrownBy(() -> ops.insert(Person.class).withBulkMode(null)); } @Test // DATAMONGO-1563 - public void insertShouldUseDerivedCollectionName() { + void insertShouldUseDerivedCollectionName() { + + when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); ops.insert(Person.class).one(luke); @@ -92,7 +91,7 @@ public void insertShouldUseDerivedCollectionName() { } @Test // DATAMONGO-1563 - public void insertShouldUseExplicitCollectionName() { + void insertShouldUseExplicitCollectionName() { ops.insert(Person.class).inCollection(STAR_WARS).one(luke); @@ -101,7 +100,9 @@ public void insertShouldUseExplicitCollectionName() { } @Test // DATAMONGO-1563 - public void insertCollectionShouldDelegateCorrectly() { + void insertCollectionShouldDelegateCorrectly() { + + when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); ops.insert(Person.class).all(Arrays.asList(luke, han)); @@ -110,7 +111,11 @@ public void insertCollectionShouldDelegateCorrectly() { } @Test // DATAMONGO-1563 - public void bulkInsertCollectionShouldDelegateCorrectly() { + void bulkInsertCollectionShouldDelegateCorrectly() { + + when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); + when(template.bulkOps(any(), any(), any())).thenReturn(bulkOperations); + when(bulkOperations.insert(anyList())).thenReturn(bulkOperations); ops.insert(Person.class).bulk(Arrays.asList(luke, han)); @@ -123,7 +128,11 @@ public void bulkInsertCollectionShouldDelegateCorrectly() { } @Test // DATAMONGO-1563 - public void bulkInsertWithBulkModeShouldDelegateCorrectly() { + void bulkInsertWithBulkModeShouldDelegateCorrectly() { + + when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); + when(template.bulkOps(any(), any(), any())).thenReturn(bulkOperations); + when(bulkOperations.insert(anyList())).thenReturn(bulkOperations); ops.insert(Person.class).withBulkMode(BulkMode.UNORDERED).bulk(Arrays.asList(luke, han)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java index cdc66c884c..6bc43225ff 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java @@ -23,11 +23,12 @@ import lombok.Data; import lombok.NoArgsConstructor; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; @@ -40,7 +41,7 @@ * @author Christoph Strobl * @currentRead Beyond the Shadows - Brent Weeks */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ExecutableMapReduceOperationSupportUnitTests { private static final String STAR_WARS = "star-wars"; @@ -49,29 +50,27 @@ public class ExecutableMapReduceOperationSupportUnitTests { @Mock MongoTemplate template; - ExecutableMapReduceOperationSupport mapReduceOpsSupport; - - @Before - public void setUp() { - - when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); + private ExecutableMapReduceOperationSupport mapReduceOpsSupport; + @BeforeEach + void setUp() { mapReduceOpsSupport = new ExecutableMapReduceOperationSupport(template); } @Test // DATAMONGO-1929 - public void throwsExceptionOnNullTemplate() { + void throwsExceptionOnNullTemplate() { assertThatIllegalArgumentException().isThrownBy(() -> new ExecutableMapReduceOperationSupport(null)); } @Test // DATAMONGO-1929 - public void throwsExceptionOnNullDomainType() { + void throwsExceptionOnNullDomainType() { assertThatIllegalArgumentException().isThrownBy(() -> mapReduceOpsSupport.mapReduce(null)); } @Test // DATAMONGO-1929 - public void usesExtractedCollectionName() { + void usesExtractedCollectionName() { + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).all(); verify(template).mapReduce(any(Query.class), eq(Person.class), eq(STAR_WARS), eq(MAP_FUNCTION), eq(REDUCE_FUNCTION), @@ -79,7 +78,7 @@ public void usesExtractedCollectionName() { } @Test // DATAMONGO-1929 - public void usesExplicitCollectionName() { + void usesExplicitCollectionName() { mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION) .inCollection("the-night-angel").all(); @@ -89,8 +88,9 @@ public void usesExplicitCollectionName() { } @Test // DATAMONGO-1929 - public void usesMapReduceOptionsWhenPresent() { + void usesMapReduceOptionsWhenPresent() { + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); MapReduceOptions options = MapReduceOptions.options(); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).with(options).all(); @@ -99,8 +99,9 @@ public void usesMapReduceOptionsWhenPresent() { } @Test // DATAMONGO-1929 - public void usesQueryWhenPresent() { + void usesQueryWhenPresent() { + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); Query query = new BasicQuery("{ 'lastname' : 'skywalker' }"); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).matching(query).all(); @@ -109,8 +110,9 @@ public void usesQueryWhenPresent() { } @Test // DATAMONGO-1929 - public void usesProjectionWhenPresent() { + void usesProjectionWhenPresent() { + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).as(Jedi.class).all(); verify(template).mapReduce(any(Query.class), eq(Person.class), eq(STAR_WARS), eq(MAP_FUNCTION), eq(REDUCE_FUNCTION), diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java index 34e511d916..fe1a5ee64c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/GeoCommandStatisticsUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link GeoCommandStatistics}. 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 c2017e3251..b5c2731de7 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 @@ -23,8 +23,8 @@ import java.util.Map; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.data.annotation.Transient; import org.springframework.data.convert.WritingConverter; @@ -49,7 +49,7 @@ public class MappingMongoJsonSchemaCreatorUnitTests { MongoMappingContext mappingContext; MappingMongoJsonSchemaCreator schemaCreator; - @Before + @BeforeEach public void setUp() { mappingContext = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java index 9d884a38f6..61fa339a22 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java index 98732af8d9..921a0660ad 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java @@ -18,7 +18,8 @@ import static org.assertj.core.api.Assertions.*; import org.bson.UuidRepresentation; -import org.junit.Test; +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.data.mongodb.config.ReadConcernPropertyEditor; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java index e9596901a6..ca3fe1ec06 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBeanTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.test.util.ReflectionTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java index 3acd334f5d..04cd781acd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java @@ -20,8 +20,8 @@ import java.net.UnknownHostException; import org.bson.BsonDocument; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.core.NestedRuntimeException; import org.springframework.dao.DataAccessException; @@ -50,7 +50,7 @@ public class MongoExceptionTranslatorUnitTests { MongoExceptionTranslator translator; - @Before + @BeforeEach public void setUp() { translator = new MongoExceptionTranslator(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index af65ca01fb..e332fdf235 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -43,6 +43,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.convert.converter.Converter; @@ -56,7 +57,6 @@ import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.annotation.Version; import org.springframework.data.auditing.IsNewAwareAuditingHandler; -import org.springframework.data.convert.CustomConversions; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -64,7 +64,6 @@ import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.LazyLoadingProxy; -import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.IndexField; 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 7e5951f793..1d48242d24 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 @@ -22,11 +22,13 @@ import java.util.concurrent.TimeUnit; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer; @@ -44,15 +46,16 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class QueryCursorPreparerUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class QueryCursorPreparerUnitTests { @Mock MongoDatabaseFactory factory; @Mock MongoExceptionTranslator exceptionTranslatorMock; @Mock FindIterable cursor; - @Before - public void setUp() { + @BeforeEach + void setUp() { when(factory.getExceptionTranslator()).thenReturn(exceptionTranslatorMock); when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); @@ -65,7 +68,7 @@ public void setUp() { } @Test // DATAMONGO-185 - public void appliesHintsCorrectly() { + void appliesHintsCorrectly() { Query query = query(where("foo").is("bar")).withHint("{ age: 1 }"); prepare(query); @@ -74,7 +77,7 @@ public void appliesHintsCorrectly() { } @Test // DATAMONGO-2365 - public void appliesIndexNameAsHintCorrectly() { + void appliesIndexNameAsHintCorrectly() { Query query = query(where("foo").is("bar")).withHint("idx-1"); prepare(query); @@ -83,7 +86,7 @@ public void appliesIndexNameAsHintCorrectly() { } @Test // DATAMONGO-2319 - public void appliesDocumentHintsCorrectly() { + void appliesDocumentHintsCorrectly() { Query query = query(where("foo").is("bar")).withHint(Document.parse("{ age: 1 }")); prepare(query); @@ -113,7 +116,7 @@ public void appliesDocumentHintsCorrectly() { // } @Test // DATAMONGO-957 - public void appliesMaxTimeCorrectly() { + void appliesMaxTimeCorrectly() { Query query = query(where("foo").is("bar")).maxTime(1, TimeUnit.SECONDS); prepare(query); @@ -122,7 +125,7 @@ public void appliesMaxTimeCorrectly() { } @Test // DATAMONGO-957 - public void appliesCommentCorrectly() { + void appliesCommentCorrectly() { Query query = query(where("foo").is("bar")).comment("spring data"); prepare(query); @@ -141,7 +144,7 @@ public void appliesCommentCorrectly() { // } @Test // DATAMONGO-1480 - public void appliesNoCursorTimeoutCorrectly() { + void appliesNoCursorTimeoutCorrectly() { Query query = query(where("foo").is("bar")).noCursorTimeout(); @@ -151,7 +154,7 @@ public void appliesNoCursorTimeoutCorrectly() { } @Test // DATAMONGO-1518 - public void appliesCollationCorrectly() { + void appliesCollationCorrectly() { prepare(new BasicQuery("{}").collation(Collation.of("fr"))); @@ -159,7 +162,7 @@ public void appliesCollationCorrectly() { } @Test // DATAMONGO-1311 - public void appliesBatchSizeCorrectly() { + void appliesBatchSizeCorrectly() { prepare(new BasicQuery("{}").cursorBatchSize(100)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java index 909cb204e2..5060485cf6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupportUnitTests.java @@ -20,12 +20,12 @@ import static org.mockito.Mockito.*; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.aggregation.Aggregation; @@ -34,40 +34,40 @@ * * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveAggregationOperationSupportUnitTests { @Mock ReactiveMongoTemplate template; - ReactiveAggregationOperationSupport opSupport; + private ReactiveAggregationOperationSupport opSupport; - @Before - public void setUp() { + @BeforeEach + void setUp() { opSupport = new ReactiveAggregationOperationSupport(template); } @Test // DATAMONGO-1719 - public void throwsExceptionOnNullDomainType() { + void throwsExceptionOnNullDomainType() { assertThatIllegalArgumentException().isThrownBy(() -> opSupport.aggregateAndReturn(null)); } @Test // DATAMONGO-1719 - public void throwsExceptionOnNullCollectionWhenUsed() { + void throwsExceptionOnNullCollectionWhenUsed() { assertThatIllegalArgumentException() .isThrownBy(() -> opSupport.aggregateAndReturn(Person.class).inCollection(null)); } @Test // DATAMONGO-1719 - public void throwsExceptionOnEmptyCollectionWhenUsed() { + void throwsExceptionOnEmptyCollectionWhenUsed() { assertThatIllegalArgumentException().isThrownBy(() -> opSupport.aggregateAndReturn(Person.class).inCollection("")); } @Test // DATAMONGO-1719 - public void throwsExceptionOnNullAggregation() { + void throwsExceptionOnNullAggregation() { assertThatIllegalArgumentException().isThrownBy(() -> opSupport.aggregateAndReturn(Person.class).by(null)); } @Test // DATAMONGO-1719 - public void aggregateWithUntypedAggregationAndExplicitCollection() { + void aggregateWithUntypedAggregationAndExplicitCollection() { opSupport.aggregateAndReturn(Person.class).inCollection("star-wars").by(newAggregation(project("foo"))).all(); @@ -77,7 +77,7 @@ public void aggregateWithUntypedAggregationAndExplicitCollection() { } @Test // DATAMONGO-1719 - public void aggregateWithUntypedAggregation() { + void aggregateWithUntypedAggregation() { when(template.getCollectionName(any(Class.class))).thenReturn("person"); @@ -92,7 +92,7 @@ public void aggregateWithUntypedAggregation() { } @Test // DATAMONGO-1719 - public void aggregateWithTypeAggregation() { + void aggregateWithTypeAggregation() { when(template.getCollectionName(any(Class.class))).thenReturn("person"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java index b11aa8bfe0..bb60f5f1d3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupportUnitTests.java @@ -30,12 +30,12 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; @@ -47,20 +47,20 @@ * @author Christoph Strobl * @currentRead Dawn Cook - The Decoy Princess */ -@RunWith(MockitoJUnitRunner.class) -public class ReactiveChangeStreamOperationSupportUnitTests { +@ExtendWith(MockitoExtension.class) +class ReactiveChangeStreamOperationSupportUnitTests { @Mock ReactiveMongoTemplate template; - ReactiveChangeStreamOperationSupport changeStreamSupport; + private ReactiveChangeStreamOperationSupport changeStreamSupport; - @Before - public void setUp() { + @BeforeEach + void setUp() { when(template.changeStream(any(), any(), any())).thenReturn(Flux.empty()); changeStreamSupport = new ReactiveChangeStreamOperationSupport(template); } @Test // DATAMONGO-2089 - public void listenWithoutDomainTypeUsesDocumentAsDefault() { + void listenWithoutDomainTypeUsesDocumentAsDefault() { changeStreamSupport.changeStream(Document.class).listen().subscribe(); @@ -68,7 +68,7 @@ public void listenWithoutDomainTypeUsesDocumentAsDefault() { } @Test // DATAMONGO-2089 - public void listenWithDomainTypeUsesSourceAsTarget() { + void listenWithDomainTypeUsesSourceAsTarget() { changeStreamSupport.changeStream(Person.class).listen().subscribe(); @@ -76,7 +76,7 @@ public void listenWithDomainTypeUsesSourceAsTarget() { } @Test // DATAMONGO-2089 - public void collectionNameIsPassedOnCorrectly() { + void collectionNameIsPassedOnCorrectly() { changeStreamSupport.changeStream(Person.class).watchCollection("star-wars").listen().subscribe(); @@ -84,7 +84,7 @@ public void collectionNameIsPassedOnCorrectly() { } @Test // DATAMONGO-2089 - public void listenWithDomainTypeCreatesTypedAggregation() { + void listenWithDomainTypeCreatesTypedAggregation() { Criteria criteria = where("operationType").is("insert"); changeStreamSupport.changeStream(Person.class).filter(criteria).listen().subscribe(); @@ -104,7 +104,7 @@ public void listenWithDomainTypeCreatesTypedAggregation() { } @Test // DATAMONGO-2089 - public void listenWithoutDomainTypeCreatesUntypedAggregation() { + void listenWithoutDomainTypeCreatesUntypedAggregation() { Criteria criteria = where("operationType").is("insert"); changeStreamSupport.changeStream(Document.class).filter(criteria).listen().subscribe(); @@ -125,7 +125,7 @@ public void listenWithoutDomainTypeCreatesUntypedAggregation() { } @Test // DATAMONGO-2089 - public void optionsShouldBePassedOnCorrectly() { + void optionsShouldBePassedOnCorrectly() { Document filter = new Document("$match", new Document("operationType", "insert")); @@ -142,7 +142,7 @@ public void optionsShouldBePassedOnCorrectly() { } @Test // DATAMONGO-2089 - public void optionsShouldBeCombinedCorrectly() { + void optionsShouldBeCombinedCorrectly() { Document filter = new Document("$match", new Document("operationType", "insert")); Instant resumeTimestamp = Instant.now(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java index 5387a12597..00e0c01f1a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupportUnitTests.java @@ -24,12 +24,12 @@ import java.util.Arrays; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.annotation.Id; @@ -38,21 +38,19 @@ * * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveInsertOperationSupportUnitTests { private static final String STAR_WARS = "star-wars"; @Mock ReactiveMongoTemplate template; - ReactiveInsertOperationSupport ops; + private ReactiveInsertOperationSupport ops; - Person luke, han; + private Person luke, han; - @Before - public void setUp() { - - when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); + @BeforeEach + void setUp() { ops = new ReactiveInsertOperationSupport(template); @@ -66,12 +64,14 @@ public void setUp() { } @Test // DATAMONGO-1719 - public void nullCollectionShouldThrowException() { + void nullCollectionShouldThrowException() { assertThatIllegalArgumentException().isThrownBy(() -> ops.insert(Person.class).inCollection(null)); } @Test // DATAMONGO-1719 - public void insertShouldUseDerivedCollectionName() { + void insertShouldUseDerivedCollectionName() { + + when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); ops.insert(Person.class).one(luke); @@ -84,7 +84,7 @@ public void insertShouldUseDerivedCollectionName() { } @Test // DATAMONGO-1719 - public void insertShouldUseExplicitCollectionName() { + void insertShouldUseExplicitCollectionName() { ops.insert(Person.class).inCollection(STAR_WARS).one(luke); @@ -93,7 +93,9 @@ public void insertShouldUseExplicitCollectionName() { } @Test // DATAMONGO-1719 - public void insertCollectionShouldDelegateCorrectly() { + void insertCollectionShouldDelegateCorrectly() { + + when(template.getCollectionName(any(Class.class))).thenReturn(STAR_WARS); ops.insert(Person.class).all(Arrays.asList(luke, han)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java index 18c2fd56db..07e0b743bb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java @@ -23,11 +23,11 @@ import lombok.Data; import lombok.NoArgsConstructor; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; @@ -41,7 +41,7 @@ * @author Christoph Strobl * @currentRead Beyond the Shadows - Brent Weeks */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveMapReduceOperationSupportUnitTests { private static final String STAR_WARS = "star-wars"; @@ -50,28 +50,27 @@ public class ReactiveMapReduceOperationSupportUnitTests { @Mock ReactiveMongoTemplate template; - ReactiveMapReduceOperationSupport mapReduceOpsSupport; - - @Before - public void setUp() { - - when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); + private ReactiveMapReduceOperationSupport mapReduceOpsSupport; + @BeforeEach + void setUp() { mapReduceOpsSupport = new ReactiveMapReduceOperationSupport(template); } @Test // DATAMONGO-1929 - public void throwsExceptionOnNullTemplate() { + void throwsExceptionOnNullTemplate() { assertThatIllegalArgumentException().isThrownBy(() -> new ExecutableMapReduceOperationSupport(null)); } @Test // DATAMONGO-1929 - public void throwsExceptionOnNullDomainType() { + void throwsExceptionOnNullDomainType() { assertThatIllegalArgumentException().isThrownBy(() -> mapReduceOpsSupport.mapReduce(null)); } @Test // DATAMONGO-1929 - public void usesExtractedCollectionName() { + void usesExtractedCollectionName() { + + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).all(); @@ -80,7 +79,7 @@ public void usesExtractedCollectionName() { } @Test // DATAMONGO-1929 - public void usesExplicitCollectionName() { + void usesExplicitCollectionName() { mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION) .inCollection("the-night-angel").all(); @@ -90,7 +89,9 @@ public void usesExplicitCollectionName() { } @Test // DATAMONGO-1929 - public void usesMapReduceOptionsWhenPresent() { + void usesMapReduceOptionsWhenPresent() { + + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); MapReduceOptions options = MapReduceOptions.options(); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).with(options).all(); @@ -100,7 +101,9 @@ public void usesMapReduceOptionsWhenPresent() { } @Test // DATAMONGO-1929 - public void usesQueryWhenPresent() { + void usesQueryWhenPresent() { + + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); Query query = new BasicQuery("{ 'lastname' : 'skywalker' }"); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).matching(query).all(); @@ -110,7 +113,9 @@ public void usesQueryWhenPresent() { } @Test // DATAMONGO-1929 - public void usesProjectionWhenPresent() { + void usesProjectionWhenPresent() { + + when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS); mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION).as(Jedi.class).all(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index a956372c4b..b1f678bda7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -57,13 +57,13 @@ @ExtendWith(MongoClientExtension.class) public class ReactiveMongoTemplateIndexTests { - static @Client MongoClient client; + private static @Client MongoClient client; - SimpleReactiveMongoDatabaseFactory factory; - ReactiveMongoTemplate template; + private SimpleReactiveMongoDatabaseFactory factory; + private ReactiveMongoTemplate template; @BeforeEach - public void setUp() { + void setUp() { factory = new SimpleReactiveMongoDatabaseFactory(client, "reactive-template-index-tests"); template = new ReactiveMongoTemplate(factory); @@ -74,11 +74,11 @@ public void setUp() { } @AfterEach - public void cleanUp() {} + void cleanUp() {} @Test // DATAMONGO-1444 @RepeatFailedTest(3) - public void testEnsureIndexShouldCreateIndex() { + void testEnsureIndexShouldCreateIndex() { Person p1 = new Person("Oliver"); p1.setAge(25); @@ -114,7 +114,7 @@ public void testEnsureIndexShouldCreateIndex() { @Test // DATAMONGO-1444 @RepeatFailedTest(3) - public void getIndexInfoShouldReturnCorrectIndex() { + void getIndexInfoShouldReturnCorrectIndex() { Person p1 = new Person("Oliver"); p1.setAge(25); @@ -145,7 +145,7 @@ public void getIndexInfoShouldReturnCorrectIndex() { @Test // DATAMONGO-1444, DATAMONGO-2264 @RepeatFailedTest(3) - public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { + void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { template.indexOps(Person.class).dropAllIndexes() // .as(StepVerifier::create) // @@ -197,7 +197,7 @@ public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { @Test // DATAMONGO-1928 @RepeatFailedTest(3) - public void shouldCreateIndexOnAccess() { + void shouldCreateIndexOnAccess() { StepVerifier.create(template.getCollection("indexedSample").listIndexes(Document.class)).expectNextCount(0) .verifyComplete(); @@ -213,7 +213,7 @@ public void shouldCreateIndexOnAccess() { @Test // DATAMONGO-1928, DATAMONGO-2264 @RepeatFailedTest(3) - public void indexCreationShouldFail() throws InterruptedException { + void indexCreationShouldFail() throws InterruptedException { Flux.from(factory.getMongoDatabase().getCollection("indexfail") // .createIndex(new Document("field", 1), new IndexOptions().name("foo").unique(true).sparse(true))) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index 0cd95d6a4e..6b125629c7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -47,10 +47,11 @@ import org.bson.BsonTimestamp; import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.dao.DataIntegrityViolationException; @@ -96,11 +97,11 @@ @ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) public class ReactiveMongoTemplateTests { - public static final String DB_NAME = "reactive-mongo-template-tests"; - static @Client MongoClient client; + private static final String DB_NAME = "reactive-mongo-template-tests"; + private static @Client MongoClient client; - ConfigurableApplicationContext context = new GenericApplicationContext(); - ReactiveMongoTestTemplate template = new ReactiveMongoTestTemplate(cfg -> { + private ConfigurableApplicationContext context = new GenericApplicationContext(); + private ReactiveMongoTestTemplate template = new ReactiveMongoTestTemplate(cfg -> { cfg.configureDatabaseFactory(it -> { @@ -113,19 +114,21 @@ public class ReactiveMongoTemplateTests { }); }); - ReactiveMongoDatabaseFactory factory = template.getDatabaseFactory(); + @BeforeEach + void setUp() { - @AfterEach - public void setUp() { + template + .flush(Person.class, MyPerson.class, Sample.class, Venue.class, PersonWithVersionPropertyOfTypeInteger.class) // + .as(StepVerifier::create) // + .verifyComplete(); - template.flush().as(StepVerifier::create).verifyComplete(); - template.flush("people", "collection").as(StepVerifier::create).verifyComplete(); - template.dropCollection(Person.class).as(StepVerifier::create).verifyComplete(); - template.dropCollection("personX").as(StepVerifier::create).verifyComplete(); + template.flush("people", "collection", "personX", "unique_person").as(StepVerifier::create).verifyComplete(); } + private ReactiveMongoDatabaseFactory factory = template.getDatabaseFactory(); + @Test // DATAMONGO-1444 - public void insertSetsId() { + void insertSetsId() { PersonWithAList person = new PersonWithAList(); assert person.getId() == null; @@ -139,7 +142,7 @@ public void insertSetsId() { } @Test // DATAMONGO-1444 - public void insertAllSetsId() { + void insertAllSetsId() { PersonWithAList person = new PersonWithAList(); @@ -152,7 +155,7 @@ public void insertAllSetsId() { } @Test // DATAMONGO-1444 - public void insertCollectionSetsId() { + void insertCollectionSetsId() { PersonWithAList person = new PersonWithAList(); @@ -165,7 +168,7 @@ public void insertCollectionSetsId() { } @Test // DATAMONGO-1444 - public void saveSetsId() { + void saveSetsId() { PersonWithAList person = new PersonWithAList(); assert person.getId() == null; @@ -179,7 +182,7 @@ public void saveSetsId() { } @Test // DATAMONGO-1444 - public void insertsSimpleEntityCorrectly() { + void insertsSimpleEntityCorrectly() { Person person = new Person("Mark"); person.setAge(35); @@ -195,7 +198,7 @@ public void insertsSimpleEntityCorrectly() { } @Test // DATAMONGO-1444 - public void simpleInsertDoesNotAllowArrays() { + void simpleInsertDoesNotAllowArrays() { Person person = new Person("Mark"); person.setAge(35); @@ -204,7 +207,7 @@ public void simpleInsertDoesNotAllowArrays() { } @Test // DATAMONGO-1444 - public void simpleInsertDoesNotAllowCollections() { + void simpleInsertDoesNotAllowCollections() { Person person = new Person("Mark"); person.setAge(35); @@ -213,7 +216,7 @@ public void simpleInsertDoesNotAllowCollections() { } @Test // DATAMONGO-1444 - public void insertsSimpleEntityWithSuppliedCollectionNameCorrectly() { + void insertsSimpleEntityWithSuppliedCollectionNameCorrectly() { Person person = new Person("Homer"); person.setAge(35); @@ -229,7 +232,7 @@ public void insertsSimpleEntityWithSuppliedCollectionNameCorrectly() { } @Test // DATAMONGO-1444 - public void insertBatchCorrectly() { + void insertBatchCorrectly() { List people = Arrays.asList(new Person("Dick", 22), new Person("Harry", 23), new Person("Tom", 21)); @@ -240,12 +243,12 @@ public void insertBatchCorrectly() { template.find(new Query().with(Sort.by("firstname")), Person.class) // .as(StepVerifier::create) // - .expectNextSequence(people) // + .expectNextCount(3) /// .verifyComplete(); } @Test // DATAMONGO-1444 - public void insertBatchWithSuppliedCollectionNameCorrectly() { + void insertBatchWithSuppliedCollectionNameCorrectly() { List people = Arrays.asList(new Person("Dick", 22), new Person("Harry", 23), new Person("Tom", 21)); @@ -256,12 +259,12 @@ public void insertBatchWithSuppliedCollectionNameCorrectly() { template.find(new Query().with(Sort.by("firstname")), Person.class, "people") // .as(StepVerifier::create) // - .expectNextSequence(people) // + .expectNextCount(3) // .verifyComplete(); } @Test // DATAMONGO-1444 - public void insertBatchWithSuppliedEntityTypeCorrectly() { + void insertBatchWithSuppliedEntityTypeCorrectly() { List people = Arrays.asList(new Person("Dick", 22), new Person("Harry", 23), new Person("Tom", 21)); @@ -272,12 +275,12 @@ public void insertBatchWithSuppliedEntityTypeCorrectly() { template.find(new Query().with(Sort.by("firstname")), Person.class) // .as(StepVerifier::create) // - .expectNextSequence(people) // + .expectNextCount(3) // .verifyComplete(); } @Test // DATAMONGO-1444 - public void testAddingToList() { + void testAddingToList() { PersonWithAList person = createPersonWithAList("Sven", 22); template.insert(person) // @@ -322,7 +325,7 @@ public void testAddingToList() { } @Test // DATAMONGO-1444 - public void testFindOneWithSort() { + void testFindOneWithSort() { PersonWithAList sven = createPersonWithAList("Sven", 22); PersonWithAList erik = createPersonWithAList("Erik", 21); @@ -346,7 +349,7 @@ public void testFindOneWithSort() { } @Test // DATAMONGO-1444 - public void bogusUpdateDoesNotTriggerException() { + void bogusUpdateDoesNotTriggerException() { ReactiveMongoTemplate mongoTemplate = new ReactiveMongoTemplate(factory); mongoTemplate.setWriteResultChecking(WriteResultChecking.EXCEPTION); @@ -367,7 +370,7 @@ public void bogusUpdateDoesNotTriggerException() { } @Test // DATAMONGO-1444 - public void updateFirstByEntityTypeShouldUpdateObject() { + void updateFirstByEntityTypeShouldUpdateObject() { Person person = new Person("Oliver2", 25); template.insert(person) // @@ -381,7 +384,7 @@ public void updateFirstByEntityTypeShouldUpdateObject() { } @Test // DATAMONGO-1444 - public void updateFirstByCollectionNameShouldUpdateObjects() { + void updateFirstByCollectionNameShouldUpdateObjects() { Person person = new Person("Oliver2", 25); template.insert(person, "people") // @@ -395,7 +398,7 @@ public void updateFirstByCollectionNameShouldUpdateObjects() { } @Test // DATAMONGO-1444 - public void updateMultiByEntityTypeShouldUpdateObjects() { + void updateMultiByEntityTypeShouldUpdateObjects() { Query query = new Query( new Criteria().orOperator(where("firstName").is("Walter Jr"), where("firstName").is("Walter"))); @@ -411,7 +414,7 @@ public void updateMultiByEntityTypeShouldUpdateObjects() { } @Test // DATAMONGO-1444 - public void updateMultiByCollectionNameShouldUpdateObject() { + void updateMultiByCollectionNameShouldUpdateObject() { Query query = new Query( new Criteria().orOperator(where("firstName").is("Walter Jr"), where("firstName").is("Walter"))); @@ -432,7 +435,7 @@ public void updateMultiByCollectionNameShouldUpdateObject() { } @Test // DATAMONGO-1444 - public void throwsExceptionForDuplicateIds() { + void throwsExceptionForDuplicateIds() { ReactiveMongoTemplate template = new ReactiveMongoTemplate(factory); template.setWriteResultChecking(WriteResultChecking.EXCEPTION); @@ -452,7 +455,7 @@ public void throwsExceptionForDuplicateIds() { } @Test // DATAMONGO-1444 - public void throwsExceptionForUpdateWithInvalidPushOperator() { + void throwsExceptionForUpdateWithInvalidPushOperator() { ReactiveMongoTemplate template = new ReactiveMongoTemplate(factory); template.setWriteResultChecking(WriteResultChecking.EXCEPTION); @@ -475,7 +478,7 @@ public void throwsExceptionForUpdateWithInvalidPushOperator() { } @Test // DATAMONGO-1444 - public void rejectsDuplicateIdInInsertAll() { + void rejectsDuplicateIdInInsertAll() { ReactiveMongoTemplate template = new ReactiveMongoTemplate(factory); template.setWriteResultChecking(WriteResultChecking.EXCEPTION); @@ -490,7 +493,7 @@ public void rejectsDuplicateIdInInsertAll() { } @Test // DATAMONGO-1444 - public void testFindAndUpdate() { + void testFindAndUpdate() { template.insertAll(Arrays.asList(new Person("Tom", 21), new Person("Dick", 22), new Person("Harry", 23))) // .as(StepVerifier::create) // @@ -527,7 +530,7 @@ public void testFindAndUpdate() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldReplaceDocument() { + void findAndReplaceShouldReplaceDocument() { org.bson.Document doc = new org.bson.Document("foo", "bar"); template.save(doc, "findandreplace").as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -548,7 +551,7 @@ public void findAndReplaceShouldReplaceDocument() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldErrorOnIdPresent() { + void findAndReplaceShouldErrorOnIdPresent() { template.save(new MyPerson("Walter")).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -561,21 +564,21 @@ public void findAndReplaceShouldErrorOnIdPresent() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldErrorOnSkip() { + void findAndReplaceShouldErrorOnSkip() { assertThatIllegalArgumentException().isThrownBy(() -> template .findAndReplace(query(where("name").is("Walter")).skip(10), new MyPerson("Heisenberg")).subscribe()); } @Test // DATAMONGO-1827 - public void findAndReplaceShouldErrorOnLimit() { + void findAndReplaceShouldErrorOnLimit() { assertThatIllegalArgumentException().isThrownBy(() -> template .findAndReplace(query(where("name").is("Walter")).limit(10), new MyPerson("Heisenberg")).subscribe()); } @Test // DATAMONGO-1827 - public void findAndReplaceShouldConsiderSortAndUpdateFirstIfMultipleFound() { + void findAndReplaceShouldConsiderSortAndUpdateFirstIfMultipleFound() { MyPerson walter1 = new MyPerson("Walter 1"); MyPerson walter2 = new MyPerson("Walter 2"); @@ -592,7 +595,7 @@ public void findAndReplaceShouldConsiderSortAndUpdateFirstIfMultipleFound() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldReplaceObject() { + void findAndReplaceShouldReplaceObject() { MyPerson person = new MyPerson("Walter"); template.save(person) // @@ -611,7 +614,7 @@ public void findAndReplaceShouldReplaceObject() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldConsiderFields() { + void findAndReplaceShouldConsiderFields() { MyPerson person = new MyPerson("Walter"); person.address = new Address("TX", "Austin"); @@ -633,7 +636,7 @@ public void findAndReplaceShouldConsiderFields() { } @Test // DATAMONGO-1827 - public void findAndReplaceNonExistingWithUpsertFalse() { + void findAndReplaceNonExistingWithUpsertFalse() { template.findAndReplace(query(where("name").is("Walter")), new MyPerson("Heisenberg")) // .as(StepVerifier::create) // @@ -643,7 +646,7 @@ public void findAndReplaceNonExistingWithUpsertFalse() { } @Test // DATAMONGO-1827 - public void findAndReplaceNonExistingWithUpsertTrue() { + void findAndReplaceNonExistingWithUpsertTrue() { template .findAndReplace(query(where("name").is("Walter")), new MyPerson("Heisenberg"), @@ -655,7 +658,7 @@ public void findAndReplaceNonExistingWithUpsertTrue() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldProjectReturnedObjectCorrectly() { + void findAndReplaceShouldProjectReturnedObjectCorrectly() { MyPerson person = new MyPerson("Walter"); template.save(person) // @@ -673,7 +676,7 @@ public void findAndReplaceShouldProjectReturnedObjectCorrectly() { } @Test // DATAMONGO-1827 - public void findAndReplaceShouldReplaceObjectReturingNew() { + void findAndReplaceShouldReplaceObjectReturingNew() { MyPerson person = new MyPerson("Walter"); template.save(person) // @@ -691,7 +694,7 @@ public void findAndReplaceShouldReplaceObjectReturingNew() { } @Test // DATAMONGO-1444 - public void testFindAllAndRemoveFullyReturnsAndRemovesDocuments() { + void testFindAllAndRemoveFullyReturnsAndRemovesDocuments() { Sample spring = new Sample("100", "spring"); Sample data = new Sample("200", "data"); @@ -716,7 +719,7 @@ public void testFindAllAndRemoveFullyReturnsAndRemovesDocuments() { } @Test // DATAMONGO-2219 - public void testFindAllAndRemoveReturnsEmptyWithoutMatches() { + void testFindAllAndRemoveReturnsEmptyWithoutMatches() { Query qry = query(where("field").in("spring", "mongodb")); template.findAllAndRemove(qry, Sample.class) // @@ -729,7 +732,7 @@ public void testFindAllAndRemoveReturnsEmptyWithoutMatches() { } @Test // DATAMONGO-1774 - public void testFindAllAndRemoveByCollectionReturnsAndRemovesDocuments() { + void testFindAllAndRemoveByCollectionReturnsAndRemovesDocuments() { Sample spring = new Sample("100", "spring"); Sample data = new Sample("200", "data"); @@ -754,12 +757,12 @@ public void testFindAllAndRemoveByCollectionReturnsAndRemovesDocuments() { } @Test // DATAMONGO-1774 - public void removeWithNullShouldThrowError() { + void removeWithNullShouldThrowError() { assertThatIllegalArgumentException().isThrownBy(() -> template.remove((Object) null).subscribe()); } @Test // DATAMONGO-1774 - public void removeWithEmptyMonoShouldDoNothing() { + void removeWithEmptyMonoShouldDoNothing() { Sample spring = new Sample("100", "spring"); Sample data = new Sample("200", "data"); @@ -778,7 +781,7 @@ public void removeWithEmptyMonoShouldDoNothing() { } @Test // DATAMONGO-1774 - public void removeWithMonoShouldDeleteElement() { + void removeWithMonoShouldDeleteElement() { Sample spring = new Sample("100", "spring"); Sample data = new Sample("200", "data"); @@ -794,7 +797,7 @@ public void removeWithMonoShouldDeleteElement() { } @Test // DATAMONGO-1774 - public void removeWithMonoAndCollectionShouldDeleteElement() { + void removeWithMonoAndCollectionShouldDeleteElement() { Sample spring = new Sample("100", "spring"); Sample data = new Sample("200", "data"); @@ -812,7 +815,7 @@ public void removeWithMonoAndCollectionShouldDeleteElement() { } @Test // DATAMONGO-2195 - public void removeVersionedEntityConsidersVersion() { + void removeVersionedEntityConsidersVersion() { PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger(); person.firstName = "Dave"; @@ -842,7 +845,7 @@ public void removeVersionedEntityConsidersVersion() { } @Test // DATAMONGO-1444 - public void optimisticLockingHandling() { + void optimisticLockingHandling() { // Init version PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger(); @@ -887,7 +890,7 @@ public void optimisticLockingHandling() { } @Test // DATAMONGO-1444 - public void doesNotFailOnVersionInitForUnversionedEntity() { + void doesNotFailOnVersionInitForUnversionedEntity() { Document dbObject = new Document(); dbObject.put("firstName", "Oliver"); @@ -900,7 +903,7 @@ public void doesNotFailOnVersionInitForUnversionedEntity() { } @Test // DATAMONGO-1444 - public void removesObjectFromExplicitCollection() { + void removesObjectFromExplicitCollection() { String collectionName = "explicit"; template.remove(new Query(), collectionName).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -923,7 +926,7 @@ public void removesObjectFromExplicitCollection() { } @Test // DATAMONGO-1444 - public void savesMapCorrectly() { + void savesMapCorrectly() { Map map = new HashMap<>(); map.put("key", "value"); @@ -936,12 +939,12 @@ public void savesMapCorrectly() { @Test // DATAMONGO-1444, DATAMONGO-1730, DATAMONGO-2150 - public void savesMongoPrimitiveObjectCorrectly() { + void savesMongoPrimitiveObjectCorrectly() { assertThatExceptionOfType(MappingException.class).isThrownBy(() -> template.save(new Object(), "collection")); } @Test // DATAMONGO-1444 - public void savesPlainDbObjectCorrectly() { + void savesPlainDbObjectCorrectly() { Document dbObject = new Document("foo", "bar"); @@ -954,7 +957,7 @@ public void savesPlainDbObjectCorrectly() { } @Test // DATAMONGO-1444, DATAMONGO-1730 - public void rejectsPlainObjectWithOutExplicitCollection() { + void rejectsPlainObjectWithOutExplicitCollection() { Document dbObject = new Document("foo", "bar"); @@ -968,7 +971,7 @@ public void rejectsPlainObjectWithOutExplicitCollection() { } @Test // DATAMONGO-1444 - public void readsPlainDbObjectById() { + void readsPlainDbObjectById() { Document dbObject = new Document("foo", "bar"); template.save(dbObject, "collection") // @@ -986,7 +989,7 @@ public void readsPlainDbObjectById() { } @Test // DATAMONGO-1444 - public void geoNear() { + void geoNear() { List venues = Arrays.asList(TestEntities.geolocation().pennStation(), // TestEntities.geolocation().tenGenOffice(), // @@ -1017,7 +1020,7 @@ public void geoNear() { } @Test // DATAMONGO-1444 - public void writesPlainString() { + void writesPlainString() { template.save("{ 'foo' : 'bar' }", "collection") // .as(StepVerifier::create) // @@ -1026,12 +1029,12 @@ public void writesPlainString() { } @Test // DATAMONGO-1444, DATAMONGO-2150 - public void rejectsNonJsonStringForSave() { + void rejectsNonJsonStringForSave() { assertThatExceptionOfType(MappingException.class).isThrownBy(() -> template.save("Foobar!", "collection")); } @Test // DATAMONGO-1444 - public void initializesVersionOnInsert() { + void initializesVersionOnInsert() { PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger(); person.firstName = "Dave"; @@ -1045,7 +1048,7 @@ public void initializesVersionOnInsert() { } @Test // DATAMONGO-1444 - public void initializesVersionOnBatchInsert() { + void initializesVersionOnBatchInsert() { PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger(); person.firstName = "Dave"; @@ -1059,7 +1062,7 @@ public void initializesVersionOnBatchInsert() { } @Test // DATAMONGO-1992 - public void initializesIdAndVersionAndOfImmutableObject() { + void initializesIdAndVersionAndOfImmutableObject() { ImmutableVersioned versioned = new ImmutableVersioned(); @@ -1078,7 +1081,7 @@ public void initializesIdAndVersionAndOfImmutableObject() { } @Test // DATAMONGO-1444 - public void queryCanBeNull() { + void queryCanBeNull() { template.findAll(PersonWithIdPropertyOfTypeObjectId.class) // .as(StepVerifier::create) // @@ -1090,7 +1093,7 @@ public void queryCanBeNull() { } @Test // DATAMONGO-1444 - public void versionsObjectIntoDedicatedCollection() { + void versionsObjectIntoDedicatedCollection() { PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger(); person.firstName = "Dave"; @@ -1109,7 +1112,7 @@ public void versionsObjectIntoDedicatedCollection() { } @Test // DATAMONGO-1444 - public void correctlySetsLongVersionProperty() { + void correctlySetsLongVersionProperty() { PersonWithVersionPropertyOfTypeLong person = new PersonWithVersionPropertyOfTypeLong(); person.firstName = "Dave"; @@ -1122,11 +1125,11 @@ public void correctlySetsLongVersionProperty() { } @Test // DATAMONGO-1444 - public void throwsExceptionForIndexViolationIfConfigured() { + void throwsExceptionForIndexViolationIfConfigured() { ReactiveMongoTemplate template = new ReactiveMongoTemplate(factory); template.setWriteResultChecking(WriteResultChecking.EXCEPTION); - template.indexOps(Person.class) // + template.indexOps("unique_person") // .ensureIndex(new Index().on("firstName", Direction.DESC).unique()) // .as(StepVerifier::create) // .expectNextCount(1) // @@ -1135,7 +1138,7 @@ public void throwsExceptionForIndexViolationIfConfigured() { Person person = new Person(new ObjectId(), "Amol"); person.setAge(28); - template.save(person) // + template.save(person, "unique_person") // .as(StepVerifier::create) // .expectNextCount(1) // .verifyComplete(); @@ -1143,13 +1146,16 @@ public void throwsExceptionForIndexViolationIfConfigured() { person = new Person(new ObjectId(), "Amol"); person.setAge(28); - template.save(person) // + template.save(person, "unique_person") // .as(StepVerifier::create) // .verifyError(DataIntegrityViolationException.class); + + // safeguard to clean up previous state + template.dropCollection(Person.class).as(StepVerifier::create).verifyComplete(); } @Test // DATAMONGO-1444 - public void preventsDuplicateInsert() { + void preventsDuplicateInsert() { template.setWriteConcern(WriteConcern.MAJORITY); @@ -1169,7 +1175,7 @@ public void preventsDuplicateInsert() { } @Test // DATAMONGO-1444 - public void countAndFindWithoutTypeInformation() { + void countAndFindWithoutTypeInformation() { Person person = new Person(); template.save(person) // @@ -1192,7 +1198,7 @@ public void countAndFindWithoutTypeInformation() { } @Test // DATAMONGO-1444 - public void nullsPropertiesForVersionObjectUpdates() { + void nullsPropertiesForVersionObjectUpdates() { VersionedPerson person = new VersionedPerson(); person.firstname = "Dave"; @@ -1221,7 +1227,7 @@ public void nullsPropertiesForVersionObjectUpdates() { } @Test // DATAMONGO-1444 - public void nullsValuesForUpdatesOfUnversionedEntity() { + void nullsValuesForUpdatesOfUnversionedEntity() { Person person = new Person("Dave"); template.save(person). // @@ -1245,7 +1251,7 @@ public void nullsValuesForUpdatesOfUnversionedEntity() { } @Test // DATAMONGO-1444 - public void savesJsonStringCorrectly() { + void savesJsonStringCorrectly() { Document dbObject = new Document().append("first", "first").append("second", "second"); @@ -1264,7 +1270,7 @@ public void savesJsonStringCorrectly() { } @Test // DATAMONGO-1444 - public void executesExistsCorrectly() { + void executesExistsCorrectly() { Sample sample = new Sample(); template.save(sample).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1287,7 +1293,7 @@ public void executesExistsCorrectly() { } @Test // DATAMONGO-1444 - public void tailStreamsData() throws InterruptedException { + void tailStreamsData() throws InterruptedException { template.dropCollection("capped").then(template.createCollection("capped", // CollectionOptions.empty().size(1000).maxDocuments(10).capped())) @@ -1309,7 +1315,7 @@ public void tailStreamsData() throws InterruptedException { } @Test // DATAMONGO-1444 - public void tailStreamsDataUntilCancellation() throws InterruptedException { + void tailStreamsDataUntilCancellation() throws InterruptedException { template.dropCollection("capped").then(template.createCollection("capped", // CollectionOptions.empty().size(1000).maxDocuments(10).capped())) @@ -1345,7 +1351,7 @@ public void tailStreamsDataUntilCancellation() throws InterruptedException { } @Test // DATAMONGO-1761 - public void testDistinct() { + void testDistinct() { Person person1 = new Person("Christoph", 38); Person person2 = new Person("Christine", 39); @@ -1365,7 +1371,7 @@ public void testDistinct() { @Test // DATAMONGO-1803 @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") @EnableIfReplicaSetAvailable - public void changeStreamEventsShouldBeEmittedCorrectly() throws InterruptedException { + void changeStreamEventsShouldBeEmittedCorrectly() throws InterruptedException { template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1397,7 +1403,7 @@ public void changeStreamEventsShouldBeEmittedCorrectly() throws InterruptedExcep @Test // DATAMONGO-1803 @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") @EnableIfReplicaSetAvailable - public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedException { + void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedException { template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1429,7 +1435,7 @@ public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedExc @Test // DATAMONGO-1803 @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") @EnableIfReplicaSetAvailable - public void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedException { + void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedException { template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1461,8 +1467,9 @@ public void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedExce @Test // DATAMONGO-1803 @EnableIfReplicaSetAvailable - public void mapsReservedWordsCorrectly() throws InterruptedException { + void mapsReservedWordsCorrectly() throws InterruptedException { + template.dropCollection(Person.class).onErrorResume(it -> Mono.empty()).as(StepVerifier::create).verifyComplete(); template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1504,7 +1511,7 @@ public void mapsReservedWordsCorrectly() throws InterruptedException { @Test // DATAMONGO-1803 @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") @EnableIfReplicaSetAvailable - public void changeStreamEventsShouldBeResumedCorrectly() throws InterruptedException { + void changeStreamEventsShouldBeResumedCorrectly() throws InterruptedException { template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1545,7 +1552,7 @@ public void changeStreamEventsShouldBeResumedCorrectly() throws InterruptedExcep } @Test // DATAMONGO-1870 - public void removeShouldConsiderLimit() { + void removeShouldConsiderLimit() { List samples = IntStream.range(0, 100) // .mapToObj(i -> new Sample("id-" + i, i % 2 == 0 ? "stark" : "lannister")) // @@ -1562,7 +1569,7 @@ public void removeShouldConsiderLimit() { } @Test // DATAMONGO-1870 - public void removeShouldConsiderSkipAndSort() { + void removeShouldConsiderSkipAndSort() { List samples = IntStream.range(0, 100) // .mapToObj(i -> new Sample("id-" + i, i % 2 == 0 ? "stark" : "lannister")) // @@ -1581,7 +1588,7 @@ public void removeShouldConsiderSkipAndSort() { } @Test // DATAMONGO-2189 - public void afterSaveEventContainsSavedObjectUsingInsert() { + void afterSaveEventContainsSavedObjectUsingInsert() { AtomicReference saved = createAfterSaveReference(); ImmutableVersioned source = new ImmutableVersioned(); @@ -1596,7 +1603,7 @@ public void afterSaveEventContainsSavedObjectUsingInsert() { } @Test // DATAMONGO-2189 - public void afterSaveEventContainsSavedObjectUsingInsertAll() { + void afterSaveEventContainsSavedObjectUsingInsertAll() { AtomicReference saved = createAfterSaveReference(); ImmutableVersioned source = new ImmutableVersioned(); @@ -1613,8 +1620,10 @@ public void afterSaveEventContainsSavedObjectUsingInsertAll() { @Test // DATAMONGO-2012 @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") @EnableIfReplicaSetAvailable - public void watchesDatabaseCorrectly() throws InterruptedException { + void watchesDatabaseCorrectly() throws InterruptedException { + template.dropCollection(Person.class).onErrorResume(it -> Mono.empty()).as(StepVerifier::create).verifyComplete(); + template.dropCollection("personX").onErrorResume(it -> Mono.empty()).as(StepVerifier::create).verifyComplete(); template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); template.createCollection("personX").as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1654,8 +1663,9 @@ public void watchesDatabaseCorrectly() throws InterruptedException { @Test // DATAMONGO-2012, DATAMONGO-2113 @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") @EnableIfReplicaSetAvailable - public void resumesAtTimestampCorrectly() throws InterruptedException { + void resumesAtTimestampCorrectly() throws InterruptedException { + template.dropCollection(Person.class).onErrorResume(it -> Mono.empty()).as(StepVerifier::create).verifyComplete(); template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1704,7 +1714,7 @@ public void resumesAtTimestampCorrectly() throws InterruptedException { @Test // DATAMONGO-2115 @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") @EnableIfReplicaSetAvailable - public void resumesAtBsonTimestampCorrectly() throws InterruptedException { + void resumesAtBsonTimestampCorrectly() throws InterruptedException { template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1774,7 +1784,7 @@ static class ImmutableVersioned { final @Id String id; final @Version Long version; - public ImmutableVersioned() { + ImmutableVersioned() { id = null; version = null; } @@ -1786,9 +1796,9 @@ static class Sample { @Id String id; String field; - public Sample() {} + Sample() {} - public Sample(String id, String field) { + Sample(String id, String field) { this.id = id; this.field = field; } @@ -1803,7 +1813,7 @@ public static class MyPerson { String name; Address address; - public MyPerson(String name) { + MyPerson(String name) { this.name = name; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java index aad1244fcd..868816605c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SerializationUtilsUnitTests.java @@ -22,7 +22,7 @@ import java.util.Map; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.query.SerializationUtils; import com.mongodb.BasicDBList; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java index 794e407947..c97f302471 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java @@ -21,10 +21,10 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.aop.framework.AopProxyUtils; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -42,15 +42,15 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class SimpleMongoClientDatabaseFactoryUnitTests { +@ExtendWith(MockitoExtension.class) +class SimpleMongoClientDatabaseFactoryUnitTests { @Mock MongoClient mongo; @Mock ClientSession clientSession; @Mock MongoDatabase database; @Test // DATADOC-254, DATAMONGO-1903 - public void rejectsIllegalDatabaseNames() { + void rejectsIllegalDatabaseNames() { rejectsDatabaseName("foo.bar"); rejectsDatabaseName("foo$bar"); @@ -61,14 +61,14 @@ public void rejectsIllegalDatabaseNames() { } @Test // DATADOC-254 - public void allowsDatabaseNames() { + void allowsDatabaseNames() { new SimpleMongoClientDatabaseFactory(mongo, "foo-bar"); new SimpleMongoClientDatabaseFactory(mongo, "foo_bar"); new SimpleMongoClientDatabaseFactory(mongo, "foo01231bar"); } @Test // DATADOC-295 - public void mongoUriConstructor() { + void mongoUriConstructor() { ConnectionString mongoURI = new ConnectionString( "mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); @@ -78,7 +78,7 @@ public void mongoUriConstructor() { } @Test // DATAMONGO-1158 - public void constructsMongoClientAccordingToMongoUri() { + void constructsMongoClientAccordingToMongoUri() { ConnectionString uri = new ConnectionString( "mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); @@ -88,7 +88,7 @@ public void constructsMongoClientAccordingToMongoUri() { } @Test // DATAMONGO-1880 - public void cascadedWithSessionUsesRootFactory() { + void cascadedWithSessionUsesRootFactory() { when(mongo.getDatabase("foo")).thenReturn(database); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java index 5ffb3f77fd..feaa9890cf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java @@ -21,10 +21,10 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.aop.framework.AopProxyUtils; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; @@ -39,15 +39,15 @@ * * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class SimpleReactiveMongoDatabaseFactoryUnitTests { +@ExtendWith(MockitoExtension.class) +class SimpleReactiveMongoDatabaseFactoryUnitTests { @Mock MongoClient mongoClient; @Mock ClientSession clientSession; @Mock MongoDatabase database; @Test // DATAMONGO-1880 - public void cascadedWithSessionUsesRootFactory() { + void cascadedWithSessionUsesRootFactory() { when(mongoClient.getDatabase("foo")).thenReturn(database); @@ -63,7 +63,7 @@ public void cascadedWithSessionUsesRootFactory() { } @Test // DATAMONGO-1903 - public void rejectsIllegalDatabaseNames() { + void rejectsIllegalDatabaseNames() { rejectsDatabaseName("foo.bar"); rejectsDatabaseName("foo$bar"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java index 1585705c15..1e46b48362 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java @@ -19,8 +19,8 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link AggregationOptions}. @@ -34,7 +34,7 @@ public class AggregationOptionsTests { AggregationOptions aggregationOptions; - @Before + @BeforeEach public void setup() { aggregationOptions = newAggregationOptions().explain(true) // .cursorBatchSize(1) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java index e898591bfd..0d7a1d15a5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link AggregationUpdate}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java index 51a38ec6da..001dd80047 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArrayOperatorsUnitTests.java @@ -22,7 +22,7 @@ import java.util.List; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.ArrayOperators.ArrayToObject; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java index 82057f9617..1b83a12b55 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperationUnitTests.java @@ -20,7 +20,7 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.BucketAutoOperation.Granularities; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java index 9096164618..6e9507c074 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/BucketOperationUnitTests.java @@ -19,7 +19,7 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link BucketOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java index 89a553e590..781737fb75 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link ConvertOperators}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java index c5b5992b2a..eee66ee20e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/CountOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link CountOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java index 0e73dc4344..d7ec8874fa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsUnitTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java index 5a4f958d3d..f3d4389440 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FieldsUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.aggregation.Fields.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.Fields.*; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java index 4285a592bb..1580b4efb0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java @@ -22,11 +22,12 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; @@ -37,16 +38,16 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class FilterExpressionUnitTests { +@ExtendWith(MockitoExtension.class) +class FilterExpressionUnitTests { @Mock MongoDatabaseFactory mongoDbFactory; private AggregationOperationContext aggregationContext; private MongoMappingContext mappingContext; - @Before - public void setUp() { + @BeforeEach + void setUp() { mappingContext = new MongoMappingContext(); aggregationContext = new TypeBasedAggregationOperationContext(Sales.class, mappingContext, @@ -54,7 +55,7 @@ public void setUp() { } @Test // DATAMONGO-1491 - public void shouldConstructFilterExpressionCorrectly() { + void shouldConstructFilterExpressionCorrectly() { TypedAggregation agg = Aggregation.newAggregation(Sales.class, Aggregation.project() @@ -72,7 +73,7 @@ public void shouldConstructFilterExpressionCorrectly() { } @Test // DATAMONGO-1491 - public void shouldConstructFilterExpressionCorrectlyWhenUsingFilterOnProjectionBuilder() { + void shouldConstructFilterExpressionCorrectlyWhenUsingFilterOnProjectionBuilder() { TypedAggregation agg = Aggregation.newAggregation(Sales.class, Aggregation.project().and("items") .filter("item", AggregationFunctionExpressions.GTE.of(Fields.field("item.price"), 100)).as("items")); @@ -88,7 +89,7 @@ public void shouldConstructFilterExpressionCorrectlyWhenUsingFilterOnProjectionB } @Test // DATAMONGO-1491 - public void shouldConstructFilterExpressionCorrectlyWhenInputMapToArray() { + void shouldConstructFilterExpressionCorrectlyWhenInputMapToArray() { TypedAggregation agg = Aggregation.newAggregation(Sales.class, Aggregation.project().and(filter(Arrays. asList(1, "a", 2, null, 3.1D, 4, "5")).as("num") @@ -105,7 +106,7 @@ public void shouldConstructFilterExpressionCorrectlyWhenInputMapToArray() { } @Test // DATAMONGO-2320 - public void shouldConstructFilterExpressionCorrectlyWhenConditionContainsFieldReference() { + void shouldConstructFilterExpressionCorrectlyWhenConditionContainsFieldReference() { Aggregation agg = Aggregation.newAggregation(Aggregation.project().and((ctx) -> new Document()).as("field-1") .and(filter("items").as("item").by(ComparisonOperators.valueOf("item.price").greaterThan("field-1"))) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java index 2fe72368a5..720eb4c135 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java @@ -20,7 +20,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.annotation.Id; import org.springframework.data.geo.Distance; import org.springframework.data.mongodb.core.DocumentTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java index 09b01fa5ba..62a85692ae 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperationUnitTests.java @@ -20,7 +20,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.query.Criteria; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java index 33404d8975..6239b3d10f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java @@ -22,7 +22,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.query.Criteria; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java index 5e4bd6eb2c..94ed8cd6b5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/LookupOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.DocumentTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java index 0742ac937f..3c5a8f2376 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ObjectOperatorsUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.Aggregation.SystemVariable; import org.springframework.data.mongodb.core.aggregation.ObjectOperators.MergeObjects; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java index e3e70a958c..8cc45db021 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java @@ -21,7 +21,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link OutOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index 84e35119fa..3a7ca1f5d4 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -28,7 +28,7 @@ import java.util.List; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java index b83480de06..40aab9daa4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationUnitTests.java @@ -23,11 +23,13 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; @@ -43,20 +45,21 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class ReactiveAggregationUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class ReactiveAggregationUnitTests { - static final String INPUT_COLLECTION = "collection-1"; + private static final String INPUT_COLLECTION = "collection-1"; - ReactiveMongoTemplate template; - ReactiveMongoDatabaseFactory factory; + private ReactiveMongoTemplate template; + private ReactiveMongoDatabaseFactory factory; @Mock MongoClient mongoClient; @Mock MongoDatabase db; @Mock MongoCollection collection; @Mock AggregatePublisher publisher; - @Before - public void setUp() { + @BeforeEach + void setUp() { factory = new SimpleReactiveMongoDatabaseFactory(mongoClient, "db"); template = new ReactiveMongoTemplate(factory); @@ -69,23 +72,23 @@ public void setUp() { } @Test // DATAMONGO-1646 - public void shouldHandleMissingInputCollection() { + void shouldHandleMissingInputCollection() { assertThatIllegalArgumentException() .isThrownBy(() -> template.aggregate(newAggregation(), (String) null, TagCount.class)); } @Test // DATAMONGO-1646 - public void shouldHandleMissingAggregationPipeline() { + void shouldHandleMissingAggregationPipeline() { assertThatIllegalArgumentException().isThrownBy(() -> template.aggregate(null, INPUT_COLLECTION, TagCount.class)); } @Test // DATAMONGO-1646 - public void shouldHandleMissingEntityClass() { + void shouldHandleMissingEntityClass() { assertThatIllegalArgumentException().isThrownBy(() -> template.aggregate(newAggregation(), INPUT_COLLECTION, null)); } @Test // DATAMONGO-1646 - public void errorsOnExplainUsage() { + void errorsOnExplainUsage() { assertThatIllegalArgumentException().isThrownBy(() -> template.aggregate(newAggregation(Product.class, // project("name", "netPrice")) // .withOptions(AggregationOptions.builder().explain(true).build()), @@ -93,7 +96,7 @@ public void errorsOnExplainUsage() { } @Test // DATAMONGO-1646, DATAMONGO-1311 - public void appliesBatchSizeWhenPresent() { + void appliesBatchSizeWhenPresent() { when(publisher.batchSize(anyInt())).thenReturn(publisher); @@ -107,7 +110,7 @@ public void appliesBatchSizeWhenPresent() { } @Test // DATAMONGO-1646 - public void appliesCollationCorrectlyWhenPresent() { + void appliesCollationCorrectlyWhenPresent() { template.aggregate(newAggregation(Product.class, // project("name", "netPrice")) // @@ -118,7 +121,7 @@ public void appliesCollationCorrectlyWhenPresent() { } @Test // DATAMONGO-1646 - public void doesNotSetCollationWhenNotPresent() { + void doesNotSetCollationWhenNotPresent() { template.aggregate(newAggregation(Product.class, // project("name", "netPrice")) // @@ -129,7 +132,7 @@ public void doesNotSetCollationWhenNotPresent() { } @Test // DATAMONGO-1646 - public void appliesDiskUsageCorrectly() { + void appliesDiskUsageCorrectly() { template.aggregate(newAggregation(Product.class, // project("name", "netPrice")) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java index 25b231d6b6..6cf1a36305 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplaceRootDocumentOperation; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java index 6fb94db7ef..7e6a557210 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link ReplaceRootOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java index b3a40dcecd..35b6a13b01 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SampleOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link SampleOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java index b5b2d22ab9..a3c3203fa9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java @@ -20,7 +20,7 @@ import java.util.List; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.convert.QueryMapper; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java index cd9a9a7720..fd5647e99f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SkipOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link SkipOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java index 393ff4dabc..41a73972d0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperationUnitTests.java @@ -21,7 +21,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link SortByCountOperation}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java index d6a27fcfaf..3d8c38b5a2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SortOperationUnitTests.java @@ -19,7 +19,7 @@ import static org.springframework.data.mongodb.core.DocumentTestUtils.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java index a04afd5869..02a2f5f107 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit test for {@link StringOperators}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java index db281d0e4e..44fbc6ff37 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java @@ -27,11 +27,11 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.GenericConversionService; @@ -57,7 +57,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class TypeBasedAggregationOperationContextUnitTests { MongoMappingContext context; @@ -66,7 +66,7 @@ public class TypeBasedAggregationOperationContextUnitTests { @Mock DbRefResolver dbRefResolver; - @Before + @BeforeEach public void setUp() { this.context = new MongoMappingContext(); @@ -283,7 +283,7 @@ public void lookupGroupAggregationShouldOverwriteExposedFields() { assertThat(definition.get("something_totally_different")).isEqualTo(1); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-1326 + @Test // DATAMONGO-1326 public void lookupGroupAggregationShouldFailInvalidFieldReference() { TypeBasedAggregationOperationContext context = getContext(MeterData.class); @@ -291,7 +291,7 @@ public void lookupGroupAggregationShouldFailInvalidFieldReference() { lookup("OtherCollection", "resourceId", "otherId", "lookup"), group().min("lookup.otherkey").as("something_totally_different"), sort(Direction.ASC, "resourceId")); - agg.toDocument("meterData", context); + assertThatIllegalArgumentException().isThrownBy(() -> agg.toDocument("meterData", context)); } @Test // DATAMONGO-861 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java index cf7e960ef1..9bbb598b79 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java @@ -22,7 +22,7 @@ import java.util.Collections; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java index b6b1762a7e..f398b4b544 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnwindOperationUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.DocumentTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index 20289bfa21..26f6e9b8e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -20,13 +20,13 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.annotation.Id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java index fe7dc08788..feff80ebff 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverterUnitTests.java @@ -18,7 +18,7 @@ import static org.mockito.Mockito.*; import org.bson.conversions.Bson; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.mapping.context.MappingContext; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java index c7657bd1b1..5309389006 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java @@ -22,11 +22,13 @@ import java.util.HashSet; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; @@ -39,20 +41,20 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class CustomConvertersUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class CustomConvertersUnitTests { - MappingMongoConverter converter; + private MappingMongoConverter converter; @Mock BarToDocumentConverter barToDocumentConverter; @Mock DocumentToBarConverter documentToBarConverter; @Mock MongoDatabaseFactory mongoDbFactory; - MongoMappingContext context; + private MongoMappingContext context; - @Before - @SuppressWarnings("unchecked") - public void setUp() throws Exception { + @BeforeEach + void setUp() { when(barToDocumentConverter.convert(any(Bar.class))).thenReturn(new Document()); when(documentToBarConverter.convert(any(Document.class))).thenReturn(new Bar()); @@ -61,7 +63,7 @@ public void setUp() throws Exception { Arrays.asList(barToDocumentConverter, documentToBarConverter)); context = new MongoMappingContext(); - context.setInitialEntitySet(new HashSet>(Arrays.asList(Foo.class, Bar.class))); + context.setInitialEntitySet(new HashSet<>(Arrays.asList(Foo.class, Bar.class))); context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); context.initialize(); @@ -71,7 +73,7 @@ public void setUp() throws Exception { } @Test // DATADOC-101 - public void nestedToDocumentConverterGetsInvoked() { + void nestedToDocumentConverterGetsInvoked() { Foo foo = new Foo(); foo.bar = new Bar(); @@ -81,7 +83,7 @@ public void nestedToDocumentConverterGetsInvoked() { } @Test // DATADOC-101 - public void nestedFromDocumentConverterGetsInvoked() { + void nestedFromDocumentConverterGetsInvoked() { Document document = new Document(); document.put("bar", new Document()); @@ -91,25 +93,25 @@ public void nestedFromDocumentConverterGetsInvoked() { } @Test // DATADOC-101 - public void toDocumentConverterGetsInvoked() { + void toDocumentConverterGetsInvoked() { converter.write(new Bar(), new Document()); verify(barToDocumentConverter).convert(any(Bar.class)); } @Test // DATADOC-101 - public void fromDocumentConverterGetsInvoked() { + void fromDocumentConverterGetsInvoked() { converter.read(Bar.class, new Document()); verify(documentToBarConverter).convert(any(Document.class)); } @Test // DATADOC-101 - public void foo() { + void foo() { Document document = new Document(); document.put("foo", null); - assertThat(document.containsKey("foo")).isEqualTo(true); + assertThat(document).containsKey("foo"); } public static class Foo { @@ -122,11 +124,7 @@ public static class Bar { public String foo; } - private interface BarToDocumentConverter extends Converter { + private interface BarToDocumentConverter extends Converter {} - } - - private interface DocumentToBarConverter extends Converter { - - } + private interface DocumentToBarConverter extends Converter {} } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java index 5697a48cb6..2311161d5d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java @@ -24,9 +24,9 @@ import java.util.Map; import org.bson.Document; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -40,7 +40,7 @@ public class DataMongo273Tests { MappingMongoConverter converter; - @Before + @BeforeEach public void setupMongoConverter() { MongoMappingContext mappingContext = new MongoMappingContext(); @@ -74,7 +74,7 @@ public void convertMapOfThings() { } @Test // DATAMONGO-294 - @Ignore("TODO: Mongo3 - this is no longer supported as DBList is no Bson type :/") + @Disabled("TODO: Mongo3 - this is no longer supported as DBList is no Bson type :/") @SuppressWarnings({ "rawtypes", "unchecked" }) public void convertListOfThings() { Plane plane = new Plane("Boeing", 4); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index 41c7ec1c7f..3ab96d6035 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -34,12 +34,12 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.annotation.AccessType; import org.springframework.data.annotation.AccessType.Type; @@ -69,7 +69,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class DbRefMappingMongoConverterUnitTests { MappingMongoConverter converter; @@ -78,7 +78,7 @@ public class DbRefMappingMongoConverterUnitTests { @Mock MongoDatabaseFactory dbFactory; DefaultDbRefResolver dbRefResolver; - @Before + @BeforeEach public void setUp() { when(dbFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index 8cb3852427..e11528ae1d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -24,13 +24,15 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -47,17 +49,18 @@ * @author Christoph Strobl * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class DefaultDbRefResolverUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class DefaultDbRefResolverUnitTests { @Mock MongoDatabaseFactory factoryMock; @Mock MongoDatabase dbMock; @Mock MongoCollection collectionMock; @Mock FindIterable cursorMock; - DefaultDbRefResolver resolver; + private DefaultDbRefResolver resolver; - @Before - public void setUp() { + @BeforeEach + void setUp() { when(factoryMock.getMongoDatabase()).thenReturn(dbMock); when(dbMock.getCollection(anyString(), any(Class.class))).thenReturn(collectionMock); @@ -68,7 +71,7 @@ public void setUp() { @Test // DATAMONGO-1194 @SuppressWarnings("unchecked") - public void bulkFetchShouldLoadDbRefsCorrectly() { + void bulkFetchShouldLoadDbRefsCorrectly() { DBRef ref1 = new DBRef("collection-1", new ObjectId()); DBRef ref2 = new DBRef("collection-1", new ObjectId()); @@ -85,25 +88,26 @@ public void bulkFetchShouldLoadDbRefsCorrectly() { assertThat($in).hasSize(2); } - @Test(expected = InvalidDataAccessApiUsageException.class) // DATAMONGO-1194 - public void bulkFetchShouldThrowExceptionWhenUsingDifferntCollectionsWithinSetOfReferences() { + @Test // DATAMONGO-1194 + void bulkFetchShouldThrowExceptionWhenUsingDifferntCollectionsWithinSetOfReferences() { DBRef ref1 = new DBRef("collection-1", new ObjectId()); DBRef ref2 = new DBRef("collection-2", new ObjectId()); - resolver.bulkFetch(Arrays.asList(ref1, ref2)); + assertThatThrownBy(() -> resolver.bulkFetch(Arrays.asList(ref1, ref2))) + .isInstanceOf(InvalidDataAccessApiUsageException.class); } @Test // DATAMONGO-1194 - public void bulkFetchShouldReturnEarlyForEmptyLists() { + void bulkFetchShouldReturnEarlyForEmptyLists() { - resolver.bulkFetch(Collections. emptyList()); + resolver.bulkFetch(Collections.emptyList()); verify(collectionMock, never()).find(Mockito.any(Document.class)); } @Test // DATAMONGO-1194 - public void bulkFetchShouldRestoreOriginalOrder() { + void bulkFetchShouldRestoreOriginalOrder() { Document o1 = new Document("_id", new ObjectId()); Document o2 = new Document("_id", new ObjectId()); @@ -117,7 +121,7 @@ public void bulkFetchShouldRestoreOriginalOrder() { } @Test // DATAMONGO-1765 - public void bulkFetchContainsDuplicates() { + void bulkFetchContainsDuplicates() { Document document = new Document("_id", new ObjectId()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java index 4f86746f82..f09265ba6f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapperUnitTests.java @@ -22,8 +22,8 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.data.convert.ConfigurableTypeInformationMapper; import org.springframework.data.convert.SimpleTypeInformationMapper; @@ -42,7 +42,7 @@ public class DefaultMongoTypeMapperUnitTests { DefaultMongoTypeMapper typeMapper; - @Before + @BeforeEach public void setUp() { configurableTypeInformationMapper = new ConfigurableTypeInformationMapper( diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java index c928e951c1..ec90b254b6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentAccessorUnitTests.java @@ -19,7 +19,7 @@ import org.bson.BsonDocument; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.mapping.Field; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java index 14263d6b61..f944723702 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoConvertersUnitTests.java @@ -21,7 +21,7 @@ import java.util.List; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.geo.Box; import org.springframework.data.geo.Circle; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java index 826e5e9340..3948927f0a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java @@ -20,7 +20,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java index f8de117a78..080d5eb1ec 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java @@ -18,10 +18,10 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -36,7 +36,7 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class LazyLoadingInterceptorUnitTests { @Mock MongoPersistentProperty propertyMock; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 7722044bae..c2af8c856d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -34,13 +34,14 @@ import org.bson.types.Decimal128; import org.bson.types.ObjectId; import org.joda.time.LocalDate; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.factory.annotation.Value; @@ -90,16 +91,16 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MappingMongoConverterUnitTests { - MappingMongoConverter converter; - MongoMappingContext mappingContext; + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; @Mock ApplicationContext context; @Mock DbRefResolver resolver; - @Before - public void setUp() { + @BeforeEach + void setUp() { MongoCustomConversions conversions = new MongoCustomConversions(); @@ -116,7 +117,7 @@ public void setUp() { } @Test - public void convertsAddressCorrectly() { + void convertsAddressCorrectly() { Address address = new Address(); address.city = "New York"; @@ -131,7 +132,7 @@ public void convertsAddressCorrectly() { } @Test - public void convertsJodaTimeTypesCorrectly() { + void convertsJodaTimeTypesCorrectly() { converter = new MappingMongoConverter(resolver, mappingContext); converter.afterPropertiesSet(); @@ -149,7 +150,7 @@ public void convertsJodaTimeTypesCorrectly() { } @Test - public void convertsCustomTypeOnConvertToMongoType() { + void convertsCustomTypeOnConvertToMongoType() { converter = new MappingMongoConverter(resolver, mappingContext); converter.afterPropertiesSet(); @@ -159,7 +160,7 @@ public void convertsCustomTypeOnConvertToMongoType() { } @Test // DATAMONGO-130 - public void writesMapTypeCorrectly() { + void writesMapTypeCorrectly() { Map map = Collections.singletonMap(Locale.US, "Foo"); @@ -170,7 +171,7 @@ public void writesMapTypeCorrectly() { } @Test // DATAMONGO-130 - public void readsMapWithCustomKeyTypeCorrectly() { + void readsMapWithCustomKeyTypeCorrectly() { org.bson.Document mapObject = new org.bson.Document(Locale.US.toString(), "Value"); org.bson.Document document = new org.bson.Document("map", mapObject); @@ -180,7 +181,7 @@ public void readsMapWithCustomKeyTypeCorrectly() { } @Test // DATAMONGO-128 - public void usesDocumentsStoredTypeIfSubtypeOfRequest() { + void usesDocumentsStoredTypeIfSubtypeOfRequest() { org.bson.Document document = new org.bson.Document(); document.put("birthDate", new LocalDate()); @@ -190,7 +191,7 @@ public void usesDocumentsStoredTypeIfSubtypeOfRequest() { } @Test // DATAMONGO-128 - public void ignoresDocumentsStoredTypeIfCompletelyDifferentTypeRequested() { + void ignoresDocumentsStoredTypeIfCompletelyDifferentTypeRequested() { org.bson.Document document = new org.bson.Document(); document.put("birthDate", new LocalDate()); @@ -200,7 +201,7 @@ public void ignoresDocumentsStoredTypeIfCompletelyDifferentTypeRequested() { } @Test - public void writesTypeDiscriminatorIntoRootObject() { + void writesTypeDiscriminatorIntoRootObject() { Person person = new Person(); @@ -212,7 +213,7 @@ public void writesTypeDiscriminatorIntoRootObject() { } @Test // DATAMONGO-136 - public void writesEnumsCorrectly() { + void writesEnumsCorrectly() { ClassWithEnumProperty value = new ClassWithEnumProperty(); value.sampleEnum = SampleEnum.FIRST; @@ -225,7 +226,7 @@ public void writesEnumsCorrectly() { } @Test // DATAMONGO-209 - public void writesEnumCollectionCorrectly() { + void writesEnumCollectionCorrectly() { ClassWithEnumProperty value = new ClassWithEnumProperty(); value.enums = Arrays.asList(SampleEnum.FIRST); @@ -241,7 +242,7 @@ public void writesEnumCollectionCorrectly() { } @Test // DATAMONGO-136 - public void readsEnumsCorrectly() { + void readsEnumsCorrectly() { org.bson.Document document = new org.bson.Document("sampleEnum", "FIRST"); ClassWithEnumProperty result = converter.read(ClassWithEnumProperty.class, document); @@ -249,7 +250,7 @@ public void readsEnumsCorrectly() { } @Test // DATAMONGO-209 - public void readsEnumCollectionsCorrectly() { + void readsEnumCollectionsCorrectly() { BasicDBList enums = new BasicDBList(); enums.add("FIRST"); @@ -263,7 +264,7 @@ public void readsEnumCollectionsCorrectly() { } @Test // DATAMONGO-144 - public void considersFieldNameWhenWriting() { + void considersFieldNameWhenWriting() { Person person = new Person(); person.firstname = "Oliver"; @@ -276,7 +277,7 @@ public void considersFieldNameWhenWriting() { } @Test // DATAMONGO-144 - public void considersFieldNameWhenReading() { + void considersFieldNameWhenReading() { org.bson.Document document = new org.bson.Document("foo", "Oliver"); Person result = converter.read(Person.class, document); @@ -285,7 +286,7 @@ public void considersFieldNameWhenReading() { } @Test - public void resolvesNestedComplexTypeForConstructorCorrectly() { + void resolvesNestedComplexTypeForConstructorCorrectly() { org.bson.Document address = new org.bson.Document("street", "110 Southwark Street"); address.put("city", "London"); @@ -301,7 +302,7 @@ public void resolvesNestedComplexTypeForConstructorCorrectly() { } @Test // DATAMONGO-145 - public void writesCollectionWithInterfaceCorrectly() { + void writesCollectionWithInterfaceCorrectly() { Person person = new Person(); person.firstname = "Oliver"; @@ -321,7 +322,7 @@ public void writesCollectionWithInterfaceCorrectly() { } @Test // DATAMONGO-145 - public void readsCollectionWithInterfaceCorrectly() { + void readsCollectionWithInterfaceCorrectly() { org.bson.Document person = new org.bson.Document(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Person.class.getName()); person.put("foo", "Oliver"); @@ -338,7 +339,7 @@ public void readsCollectionWithInterfaceCorrectly() { } @Test - public void convertsLocalesOutOfTheBox() { + void convertsLocalesOutOfTheBox() { LocaleWrapper wrapper = new LocaleWrapper(); wrapper.locale = Locale.US; @@ -354,7 +355,7 @@ public void convertsLocalesOutOfTheBox() { } @Test // DATAMONGO-161 - public void readsNestedMapsCorrectly() { + void readsNestedMapsCorrectly() { Map secondLevel = new HashMap(); secondLevel.put("key1", "value1"); @@ -378,7 +379,7 @@ public void readsNestedMapsCorrectly() { } @Test // DATACMNS-42, DATAMONGO-171 - public void writesClassWithBigDecimal() { + void writesClassWithBigDecimal() { BigDecimalContainer container = new BigDecimalContainer(); container.value = BigDecimal.valueOf(2.5d); @@ -393,7 +394,7 @@ public void writesClassWithBigDecimal() { } @Test // DATACMNS-42, DATAMONGO-171 - public void readsClassWithBigDecimal() { + void readsClassWithBigDecimal() { org.bson.Document document = new org.bson.Document("value", "2.5"); document.put("map", new org.bson.Document("foo", "2.5")); @@ -409,7 +410,7 @@ public void readsClassWithBigDecimal() { } @Test - public void writesNestedCollectionsCorrectly() { + void writesNestedCollectionsCorrectly() { CollectionWrapper wrapper = new CollectionWrapper(); wrapper.strings = Arrays.asList(Arrays.asList("Foo")); @@ -425,7 +426,7 @@ public void writesNestedCollectionsCorrectly() { } @Test // DATAMONGO-192 - public void readsEmptySetsCorrectly() { + void readsEmptySetsCorrectly() { Person person = new Person(); person.addresses = Collections.emptySet(); @@ -436,7 +437,7 @@ public void readsEmptySetsCorrectly() { } @Test - public void convertsObjectIdStringsToObjectIdCorrectly() { + void convertsObjectIdStringsToObjectIdCorrectly() { PersonPojoStringId p1 = new PersonPojoStringId("1234567890", "Text-1"); org.bson.Document doc1 = new org.bson.Document(); @@ -451,7 +452,7 @@ public void convertsObjectIdStringsToObjectIdCorrectly() { } @Test // DATAMONGO-207 - public void convertsCustomEmptyMapCorrectly() { + void convertsCustomEmptyMapCorrectly() { org.bson.Document map = new org.bson.Document(); org.bson.Document wrapper = new org.bson.Document("map", map); @@ -463,12 +464,12 @@ public void convertsCustomEmptyMapCorrectly() { } @Test // DATAMONGO-211 - public void maybeConvertHandlesNullValuesCorrectly() { + void maybeConvertHandlesNullValuesCorrectly() { assertThat(converter.convertToMongoType(null)).isNull(); } @Test // DATAMONGO-1509 - public void writesGenericTypeCorrectly() { + void writesGenericTypeCorrectly() { GenericType
      type = new GenericType
      (); type.content = new Address(); @@ -483,7 +484,7 @@ public void writesGenericTypeCorrectly() { } @Test - public void readsGenericTypeCorrectly() { + void readsGenericTypeCorrectly() { org.bson.Document address = new org.bson.Document("_class", Address.class.getName()); address.put("city", "London"); @@ -493,7 +494,7 @@ public void readsGenericTypeCorrectly() { } @Test // DATAMONGO-228 - public void writesNullValuesForMaps() { + void writesNullValuesForMaps() { ClassWithMapProperty foo = new ClassWithMapProperty(); foo.map = Collections.singletonMap(Locale.US, null); @@ -507,7 +508,7 @@ public void writesNullValuesForMaps() { } @Test - public void writesBigIntegerIdCorrectly() { + void writesBigIntegerIdCorrectly() { ClassWithBigIntegerId foo = new ClassWithBigIntegerId(); foo.id = BigInteger.valueOf(23L); @@ -525,7 +526,7 @@ public void convertsObjectsIfNecessary() { } @Test // DATAMONGO-235 - public void writesMapOfListsCorrectly() { + void writesMapOfListsCorrectly() { ClassWithMapProperty input = new ClassWithMapProperty(); input.mapOfLists = Collections.singletonMap("Foo", Arrays.asList("Bar")); @@ -546,7 +547,7 @@ public void writesMapOfListsCorrectly() { } @Test // DATAMONGO-235 - public void readsMapListValuesCorrectly() { + void readsMapListValuesCorrectly() { BasicDBList list = new BasicDBList(); list.add("Bar"); @@ -557,7 +558,7 @@ public void readsMapListValuesCorrectly() { } @Test // DATAMONGO-235 - public void writesMapsOfObjectsCorrectly() { + void writesMapsOfObjectsCorrectly() { ClassWithMapProperty input = new ClassWithMapProperty(); input.mapOfObjects = new HashMap(); @@ -579,7 +580,7 @@ public void writesMapsOfObjectsCorrectly() { } @Test // DATAMONGO-235 - public void readsMapOfObjectsListValuesCorrectly() { + void readsMapOfObjectsListValuesCorrectly() { BasicDBList list = new BasicDBList(); list.add("Bar"); @@ -590,7 +591,7 @@ public void readsMapOfObjectsListValuesCorrectly() { } @Test // DATAMONGO-245 - public void readsMapListNestedValuesCorrectly() { + void readsMapListNestedValuesCorrectly() { BasicDBList list = new BasicDBList(); list.add(new org.bson.Document("Hello", "World")); @@ -603,7 +604,7 @@ public void readsMapListNestedValuesCorrectly() { } @Test // DATAMONGO-245 - public void readsMapDoublyNestedValuesCorrectly() { + void readsMapDoublyNestedValuesCorrectly() { org.bson.Document nested = new org.bson.Document(); org.bson.Document doubly = new org.bson.Document(); @@ -620,7 +621,7 @@ public void readsMapDoublyNestedValuesCorrectly() { } @Test // DATAMONGO-245 - public void readsMapListDoublyNestedValuesCorrectly() { + void readsMapListDoublyNestedValuesCorrectly() { BasicDBList list = new BasicDBList(); org.bson.Document nested = new org.bson.Document(); @@ -639,7 +640,7 @@ public void readsMapListDoublyNestedValuesCorrectly() { } @Test // DATAMONGO-259 - public void writesListOfMapsCorrectly() { + void writesListOfMapsCorrectly() { Map map = Collections.singletonMap("Foo", Locale.ENGLISH); @@ -660,7 +661,7 @@ public void writesListOfMapsCorrectly() { } @Test // DATAMONGO-259 - public void readsListOfMapsCorrectly() { + void readsListOfMapsCorrectly() { org.bson.Document map = new org.bson.Document("Foo", "en"); @@ -678,7 +679,7 @@ public void readsListOfMapsCorrectly() { } @Test // DATAMONGO-259 - public void writesPlainMapOfCollectionsCorrectly() { + void writesPlainMapOfCollectionsCorrectly() { Map> map = Collections.singletonMap("Foo", Arrays.asList(Locale.US)); org.bson.Document result = new org.bson.Document(); @@ -696,7 +697,7 @@ public void writesPlainMapOfCollectionsCorrectly() { @Test // DATAMONGO-285 @SuppressWarnings({ "unchecked", "rawtypes" }) - public void testSaveMapWithACollectionAsValue() { + void testSaveMapWithACollectionAsValue() { Map keyValues = new HashMap(); keyValues.put("string", "hello"); @@ -721,7 +722,7 @@ public void testSaveMapWithACollectionAsValue() { @Test // DATAMONGO-309 @SuppressWarnings({ "unchecked" }) - public void writesArraysAsMapValuesCorrectly() { + void writesArraysAsMapValuesCorrectly() { ClassWithMapProperty wrapper = new ClassWithMapProperty(); wrapper.mapOfObjects = new HashMap(); @@ -743,7 +744,7 @@ public void writesArraysAsMapValuesCorrectly() { } @Test // DATAMONGO-324 - public void writesDocumentCorrectly() { + void writesDocumentCorrectly() { org.bson.Document document = new org.bson.Document(); document.put("foo", "bar"); @@ -757,7 +758,7 @@ public void writesDocumentCorrectly() { } @Test // DATAMONGO-324 - public void readsDocumentCorrectly() { + void readsDocumentCorrectly() { org.bson.Document document = new org.bson.Document(); document.put("foo", "bar"); @@ -768,7 +769,7 @@ public void readsDocumentCorrectly() { } @Test // DATAMONGO-329 - public void writesMapAsGenericFieldCorrectly() { + void writesMapAsGenericFieldCorrectly() { Map> objectToSave = new HashMap>(); objectToSave.put("test", new A("testValue")); @@ -792,7 +793,7 @@ public void writesMapAsGenericFieldCorrectly() { } @Test - public void writesIntIdCorrectly() { + void writesIntIdCorrectly() { ClassWithIntId value = new ClassWithIntId(); value.id = 5; @@ -805,7 +806,7 @@ public void writesIntIdCorrectly() { @Test // DATAMONGO-368 @SuppressWarnings("unchecked") - public void writesNullValuesForCollection() { + void writesNullValuesForCollection() { CollectionWrapper wrapper = new CollectionWrapper(); wrapper.contacts = Arrays.asList(new Person(), null); @@ -820,7 +821,7 @@ public void writesNullValuesForCollection() { } @Test // DATAMONGO-379 - public void considersDefaultingExpressionsAtConstructorArguments() { + void considersDefaultingExpressionsAtConstructorArguments() { org.bson.Document document = new org.bson.Document("foo", "bar"); document.put("foobar", 2.5); @@ -830,7 +831,7 @@ public void considersDefaultingExpressionsAtConstructorArguments() { } @Test // DATAMONGO-379 - public void usesDocumentFieldIfReferencedInAtValue() { + void usesDocumentFieldIfReferencedInAtValue() { org.bson.Document document = new org.bson.Document("foo", "bar"); document.put("something", 37); @@ -840,16 +841,17 @@ public void usesDocumentFieldIfReferencedInAtValue() { assertThat(result.bar).isEqualTo(37); } - @Test(expected = MappingInstantiationException.class) // DATAMONGO-379 - public void rejectsNotFoundConstructorParameterForPrimitiveType() { + @Test // DATAMONGO-379 + void rejectsNotFoundConstructorParameterForPrimitiveType() { org.bson.Document document = new org.bson.Document("foo", "bar"); - converter.read(DefaultedConstructorArgument.class, document); + assertThatThrownBy(() -> converter.read(DefaultedConstructorArgument.class, document)) + .isInstanceOf(MappingInstantiationException.class); } @Test // DATAMONGO-358 - public void writesListForObjectPropertyCorrectly() { + void writesListForObjectPropertyCorrectly() { Attribute attribute = new Attribute(); attribute.key = "key"; @@ -875,13 +877,13 @@ public void writesListForObjectPropertyCorrectly() { } @Test // DATAMONGO-380 - public void rejectsMapWithKeyContainingDotsByDefault() { + void rejectsMapWithKeyContainingDotsByDefault() { assertThatExceptionOfType(MappingException.class) .isThrownBy(() -> converter.write(Collections.singletonMap("foo.bar", "foobar"), new org.bson.Document())); } @Test // DATAMONGO-380 - public void escapesDotInMapKeysIfReplacementConfigured() { + void escapesDotInMapKeysIfReplacementConfigured() { converter.setMapKeyDotReplacement("~"); @@ -894,7 +896,7 @@ public void escapesDotInMapKeysIfReplacementConfigured() { @Test // DATAMONGO-380 @SuppressWarnings("unchecked") - public void unescapesDotInMapKeysIfReplacementConfigured() { + void unescapesDotInMapKeysIfReplacementConfigured() { converter.setMapKeyDotReplacement("~"); @@ -906,8 +908,8 @@ public void unescapesDotInMapKeysIfReplacementConfigured() { } @Test // DATAMONGO-382 - @Ignore("mongo3 - no longer supported") - public void convertsSetToBasicDBList() { + @Disabled("mongo3 - no longer supported") + void convertsSetToBasicDBList() { Address address = new Address(); address.city = "London"; @@ -922,7 +924,7 @@ public void convertsSetToBasicDBList() { } @Test // DATAMONGO-402 - public void readsMemberClassCorrectly() { + void readsMemberClassCorrectly() { org.bson.Document document = new org.bson.Document("inner", new org.bson.Document("value", "FOO!")); @@ -933,7 +935,7 @@ public void readsMemberClassCorrectly() { } @Test // DATAMONGO-458 - public void readEmptyCollectionIsModifiable() { + void readEmptyCollectionIsModifiable() { org.bson.Document document = new org.bson.Document("contactsSet", new BasicDBList()); CollectionWrapper wrapper = converter.read(CollectionWrapper.class, document); @@ -943,7 +945,7 @@ public void readEmptyCollectionIsModifiable() { } @Test // DATAMONGO-424 - public void readsPlainDBRefObject() { + void readsPlainDBRefObject() { DBRef dbRef = new DBRef("foo", 2); org.bson.Document document = new org.bson.Document("ref", dbRef); @@ -953,7 +955,7 @@ public void readsPlainDBRefObject() { } @Test // DATAMONGO-424 - public void readsCollectionOfDBRefs() { + void readsCollectionOfDBRefs() { DBRef dbRef = new DBRef("foo", 2); BasicDBList refs = new BasicDBList(); @@ -967,7 +969,7 @@ public void readsCollectionOfDBRefs() { } @Test // DATAMONGO-424 - public void readsDBRefMap() { + void readsDBRefMap() { DBRef dbRef = mock(DBRef.class); org.bson.Document refMap = new org.bson.Document("foo", dbRef); @@ -981,7 +983,7 @@ public void readsDBRefMap() { @Test // DATAMONGO-424 @SuppressWarnings({ "rawtypes", "unchecked" }) - public void resolvesDBRefMapValue() { + void resolvesDBRefMapValue() { when(resolver.fetch(Mockito.any(DBRef.class))).thenReturn(new org.bson.Document()); DBRef dbRef = mock(DBRef.class); @@ -996,7 +998,7 @@ public void resolvesDBRefMapValue() { } @Test // DATAMONGO-462 - public void writesURLsAsStringOutOfTheBox() throws Exception { + void writesURLsAsStringOutOfTheBox() throws Exception { URLWrapper wrapper = new URLWrapper(); wrapper.url = new URL("https://springsource.org"); @@ -1008,14 +1010,14 @@ public void writesURLsAsStringOutOfTheBox() throws Exception { } @Test // DATAMONGO-462 - public void readsURLFromStringOutOfTheBox() throws Exception { + void readsURLFromStringOutOfTheBox() throws Exception { org.bson.Document document = new org.bson.Document("url", "https://springsource.org"); URLWrapper result = converter.read(URLWrapper.class, document); assertThat(result.url).isEqualTo(new URL("https://springsource.org")); } @Test // DATAMONGO-485 - public void writesComplexIdCorrectly() { + void writesComplexIdCorrectly() { ComplexId id = new ComplexId(); id.innerId = 4711L; @@ -1033,7 +1035,7 @@ public void writesComplexIdCorrectly() { } @Test // DATAMONGO-485 - public void readsComplexIdCorrectly() { + void readsComplexIdCorrectly() { org.bson.Document innerId = new org.bson.Document("innerId", 4711L); org.bson.Document entity = new org.bson.Document("_id", innerId); @@ -1045,7 +1047,7 @@ public void readsComplexIdCorrectly() { } @Test // DATAMONGO-489 - public void readsArraysAsMapValuesCorrectly() { + void readsArraysAsMapValuesCorrectly() { BasicDBList list = new BasicDBList(); list.add("Foo"); @@ -1063,7 +1065,7 @@ public void readsArraysAsMapValuesCorrectly() { } @Test // DATAMONGO-497 - public void readsEmptyCollectionIntoConstructorCorrectly() { + void readsEmptyCollectionIntoConstructorCorrectly() { org.bson.Document source = new org.bson.Document("attributes", new BasicDBList()); @@ -1072,7 +1074,7 @@ public void readsEmptyCollectionIntoConstructorCorrectly() { } @Test // DATAMONGO-2400 - public void writeJavaTimeValuesViaCodec() { + void writeJavaTimeValuesViaCodec() { configureConverterWithNativeJavaTimeCodec(); TypeWithLocalDateTime source = new TypeWithLocalDateTime(); @@ -1107,7 +1109,7 @@ private static void assertSyntheticFieldValueOf(Object target, Object expected) } @Test // DATAMGONGO-508 - public void eagerlyReturnsDBRefObjectIfTargetAlreadyIsOne() { + void eagerlyReturnsDBRefObjectIfTargetAlreadyIsOne() { DBRef dbRef = new DBRef("collection", "id"); @@ -1117,7 +1119,7 @@ public void eagerlyReturnsDBRefObjectIfTargetAlreadyIsOne() { } @Test // DATAMONGO-523, DATAMONGO-1509 - public void considersTypeAliasAnnotation() { + void considersTypeAliasAnnotation() { Aliased aliased = new Aliased(); aliased.name = "foo"; @@ -1129,7 +1131,7 @@ public void considersTypeAliasAnnotation() { } @Test // DATAMONGO-533 - public void marshalsThrowableCorrectly() { + void marshalsThrowableCorrectly() { ThrowableWrapper wrapper = new ThrowableWrapper(); wrapper.throwable = new Exception(); @@ -1139,7 +1141,7 @@ public void marshalsThrowableCorrectly() { } @Test // DATAMONGO-592 - public void recursivelyConvertsSpELReadValue() { + void recursivelyConvertsSpELReadValue() { org.bson.Document input = org.bson.Document.parse( "{ \"_id\" : { \"$oid\" : \"50ca271c4566a2b08f2d667a\" }, \"_class\" : \"com.recorder.TestRecorder2$ObjectContainer\", \"property\" : { \"property\" : 100 } }"); @@ -1148,7 +1150,7 @@ public void recursivelyConvertsSpELReadValue() { } @Test // DATAMONGO-724 - public void mappingConsidersCustomConvertersNotWritingTypeInformation() { + void mappingConsidersCustomConvertersNotWritingTypeInformation() { Person person = new Person(); person.firstname = "Dave"; @@ -1206,7 +1208,7 @@ public Person convert(org.bson.Document source) { } @Test // DATAMONGO-743, DATAMONGO-2198 - public void readsIntoStringsOutOfTheBox() { + void readsIntoStringsOutOfTheBox() { String target = converter.read(String.class, new org.bson.Document("firstname", "Dave")); @@ -1217,7 +1219,7 @@ public void readsIntoStringsOutOfTheBox() { } @Test // DATAMONGO-766 - public void writesProjectingTypeCorrectly() { + void writesProjectingTypeCorrectly() { NestedType nested = new NestedType(); nested.c = "C"; @@ -1237,7 +1239,7 @@ public void writesProjectingTypeCorrectly() { } @Test // DATAMONGO-812, DATAMONGO-893, DATAMONGO-1509 - public void convertsListToBasicDBListAndRetainsTypeInformationForComplexObjects() { + void convertsListToBasicDBListAndRetainsTypeInformationForComplexObjects() { Address address = new Address(); address.city = "London"; @@ -1254,7 +1256,7 @@ public void convertsListToBasicDBListAndRetainsTypeInformationForComplexObjects( } @Test // DATAMONGO-812 - public void convertsListToBasicDBListWithoutTypeInformationForSimpleTypes() { + void convertsListToBasicDBListWithoutTypeInformationForSimpleTypes() { Object result = converter.convertToMongoType(Collections.singletonList("foo")); @@ -1266,7 +1268,7 @@ public void convertsListToBasicDBListWithoutTypeInformationForSimpleTypes() { } @Test // DATAMONGO-812, DATAMONGO-1509 - public void convertsArrayToBasicDBListAndRetainsTypeInformationForComplexObjects() { + void convertsArrayToBasicDBListAndRetainsTypeInformationForComplexObjects() { Address address = new Address(); address.city = "London"; @@ -1282,7 +1284,7 @@ public void convertsArrayToBasicDBListAndRetainsTypeInformationForComplexObjects } @Test // DATAMONGO-812 - public void convertsArrayToBasicDBListWithoutTypeInformationForSimpleTypes() { + void convertsArrayToBasicDBListWithoutTypeInformationForSimpleTypes() { Object result = converter.convertToMongoType(new String[] { "foo" }); @@ -1294,7 +1296,7 @@ public void convertsArrayToBasicDBListWithoutTypeInformationForSimpleTypes() { } @Test // DATAMONGO-833 - public void readsEnumSetCorrectly() { + void readsEnumSetCorrectly() { BasicDBList enumSet = new BasicDBList(); enumSet.add("SECOND"); @@ -1308,7 +1310,7 @@ public void readsEnumSetCorrectly() { } @Test // DATAMONGO-833 - public void readsEnumMapCorrectly() { + void readsEnumMapCorrectly() { org.bson.Document enumMap = new org.bson.Document("FIRST", "Dave"); ClassWithEnumProperty result = converter.read(ClassWithEnumProperty.class, @@ -1320,7 +1322,7 @@ public void readsEnumMapCorrectly() { } @Test // DATAMONGO-887 - public void readsTreeMapCorrectly() { + void readsTreeMapCorrectly() { org.bson.Document person = new org.bson.Document("foo", "Dave"); org.bson.Document treeMapOfPerson = new org.bson.Document("key", person); @@ -1334,7 +1336,7 @@ public void readsTreeMapCorrectly() { } @Test // DATAMONGO-887 - public void writesTreeMapCorrectly() { + void writesTreeMapCorrectly() { Person person = new Person(); person.firstname = "Dave"; @@ -1353,7 +1355,7 @@ public void writesTreeMapCorrectly() { } @Test // DATAMONGO-858 - public void shouldWriteEntityWithGeoBoxCorrectly() { + void shouldWriteEntityWithGeoBoxCorrectly() { ClassWithGeoBox object = new ClassWithGeoBox(); object.box = new Box(new Point(1, 2), new Point(3, 4)); @@ -1372,7 +1374,7 @@ private static org.bson.Document toDocument(Point point) { } @Test // DATAMONGO-858 - public void shouldReadEntityWithGeoBoxCorrectly() { + void shouldReadEntityWithGeoBoxCorrectly() { ClassWithGeoBox object = new ClassWithGeoBox(); object.box = new Box(new Point(1, 2), new Point(3, 4)); @@ -1387,7 +1389,7 @@ public void shouldReadEntityWithGeoBoxCorrectly() { } @Test // DATAMONGO-858 - public void shouldWriteEntityWithGeoPolygonCorrectly() { + void shouldWriteEntityWithGeoPolygonCorrectly() { ClassWithGeoPolygon object = new ClassWithGeoPolygon(); object.polygon = new Polygon(new Point(1, 2), new Point(3, 4), new Point(4, 5)); @@ -1409,7 +1411,7 @@ public void shouldWriteEntityWithGeoPolygonCorrectly() { } @Test // DATAMONGO-858 - public void shouldReadEntityWithGeoPolygonCorrectly() { + void shouldReadEntityWithGeoPolygonCorrectly() { ClassWithGeoPolygon object = new ClassWithGeoPolygon(); object.polygon = new Polygon(new Point(1, 2), new Point(3, 4), new Point(4, 5)); @@ -1424,7 +1426,7 @@ public void shouldReadEntityWithGeoPolygonCorrectly() { } @Test // DATAMONGO-858 - public void shouldWriteEntityWithGeoCircleCorrectly() { + void shouldWriteEntityWithGeoCircleCorrectly() { ClassWithGeoCircle object = new ClassWithGeoCircle(); Circle circle = new Circle(new Point(1, 2), 3); @@ -1442,7 +1444,7 @@ public void shouldWriteEntityWithGeoCircleCorrectly() { } @Test // DATAMONGO-858 - public void shouldReadEntityWithGeoCircleCorrectly() { + void shouldReadEntityWithGeoCircleCorrectly() { ClassWithGeoCircle object = new ClassWithGeoCircle(); object.circle = new Circle(new Point(1, 2), 3); @@ -1457,7 +1459,7 @@ public void shouldReadEntityWithGeoCircleCorrectly() { } @Test // DATAMONGO-858 - public void shouldWriteEntityWithGeoSphereCorrectly() { + void shouldWriteEntityWithGeoSphereCorrectly() { ClassWithGeoSphere object = new ClassWithGeoSphere(); Sphere sphere = new Sphere(new Point(1, 2), 3); @@ -1475,7 +1477,7 @@ public void shouldWriteEntityWithGeoSphereCorrectly() { } @Test // DATAMONGO-858 - public void shouldWriteEntityWithGeoSphereWithMetricDistanceCorrectly() { + void shouldWriteEntityWithGeoSphereWithMetricDistanceCorrectly() { ClassWithGeoSphere object = new ClassWithGeoSphere(); Sphere sphere = new Sphere(new Point(1, 2), new Distance(3, Metrics.KILOMETERS)); @@ -1493,7 +1495,7 @@ public void shouldWriteEntityWithGeoSphereWithMetricDistanceCorrectly() { } @Test // DATAMONGO-858 - public void shouldReadEntityWithGeoSphereCorrectly() { + void shouldReadEntityWithGeoSphereCorrectly() { ClassWithGeoSphere object = new ClassWithGeoSphere(); object.sphere = new Sphere(new Point(1, 2), 3); @@ -1508,7 +1510,7 @@ public void shouldReadEntityWithGeoSphereCorrectly() { } @Test // DATAMONGO-858 - public void shouldWriteEntityWithGeoShapeCorrectly() { + void shouldWriteEntityWithGeoShapeCorrectly() { ClassWithGeoShape object = new ClassWithGeoShape(); Sphere sphere = new Sphere(new Point(1, 2), 3); @@ -1526,8 +1528,8 @@ public void shouldWriteEntityWithGeoShapeCorrectly() { } @Test // DATAMONGO-858 - @Ignore - public void shouldReadEntityWithGeoShapeCorrectly() { + @Disabled + void shouldReadEntityWithGeoShapeCorrectly() { ClassWithGeoShape object = new ClassWithGeoShape(); Sphere sphere = new Sphere(new Point(1, 2), 3); @@ -1543,7 +1545,7 @@ public void shouldReadEntityWithGeoShapeCorrectly() { } @Test // DATAMONGO-976 - public void shouldIgnoreTextScorePropertyWhenWriting() { + void shouldIgnoreTextScorePropertyWhenWriting() { ClassWithTextScoreProperty source = new ClassWithTextScoreProperty(); source.score = Float.MAX_VALUE; @@ -1555,7 +1557,7 @@ public void shouldIgnoreTextScorePropertyWhenWriting() { } @Test // DATAMONGO-976 - public void shouldIncludeTextScorePropertyWhenReading() { + void shouldIncludeTextScorePropertyWhenReading() { ClassWithTextScoreProperty entity = converter.read(ClassWithTextScoreProperty.class, new org.bson.Document("score", 5F)); @@ -1563,7 +1565,7 @@ public void shouldIncludeTextScorePropertyWhenReading() { } @Test // DATAMONGO-1001, DATAMONGO-1509 - public void shouldWriteCglibProxiedClassTypeInformationCorrectly() { + void shouldWriteCglibProxiedClassTypeInformationCorrectly() { ProxyFactory factory = new ProxyFactory(); factory.setTargetClass(GenericType.class); @@ -1577,7 +1579,7 @@ public void shouldWriteCglibProxiedClassTypeInformationCorrectly() { } @Test // DATAMONGO-1001 - public void shouldUseTargetObjectOfLazyLoadingProxyWhenWriting() { + void shouldUseTargetObjectOfLazyLoadingProxyWhenWriting() { LazyLoadingProxy mock = mock(LazyLoadingProxy.class); @@ -1588,7 +1590,7 @@ public void shouldUseTargetObjectOfLazyLoadingProxyWhenWriting() { } @Test // DATAMONGO-1034 - public void rejectsBasicDbListToBeConvertedIntoComplexType() { + void rejectsBasicDbListToBeConvertedIntoComplexType() { List inner = new ArrayList(); inner.add("key"); @@ -1604,7 +1606,7 @@ public void rejectsBasicDbListToBeConvertedIntoComplexType() { } @Test // DATAMONGO-1058 - public void readShouldRespectExplicitFieldNameForDbRef() { + void readShouldRespectExplicitFieldNameForDbRef() { org.bson.Document source = new org.bson.Document(); source.append("explict-name-for-db-ref", new DBRef("foo", "1")); @@ -1616,7 +1618,7 @@ public void readShouldRespectExplicitFieldNameForDbRef() { } @Test // DATAMONGO-1050 - public void writeShouldUseExplicitFieldnameForIdPropertyWhenAnnotated() { + void writeShouldUseExplicitFieldnameForIdPropertyWhenAnnotated() { RootForClassWithExplicitlyRenamedIdField source = new RootForClassWithExplicitlyRenamedIdField(); source.id = "rootId"; @@ -1631,7 +1633,7 @@ public void writeShouldUseExplicitFieldnameForIdPropertyWhenAnnotated() { } @Test // DATAMONGO-1050 - public void readShouldUseExplicitFieldnameForIdPropertyWhenAnnotated() { + void readShouldUseExplicitFieldnameForIdPropertyWhenAnnotated() { org.bson.Document source = new org.bson.Document().append("_id", "rootId").append("nested", new org.bson.Document("id", "nestedId")); @@ -1645,7 +1647,7 @@ public void readShouldUseExplicitFieldnameForIdPropertyWhenAnnotated() { } @Test // DATAMONGO-1050 - public void namedIdFieldShouldExtractValueFromUnderscoreIdField() { + void namedIdFieldShouldExtractValueFromUnderscoreIdField() { org.bson.Document document = new org.bson.Document().append("_id", "A").append("id", "B"); @@ -1655,7 +1657,7 @@ public void namedIdFieldShouldExtractValueFromUnderscoreIdField() { } @Test // DATAMONGO-1050 - public void explicitlyRenamedIfFieldShouldExtractValueFromIdField() { + void explicitlyRenamedIfFieldShouldExtractValueFromIdField() { org.bson.Document document = new org.bson.Document().append("_id", "A").append("id", "B"); @@ -1666,7 +1668,7 @@ public void explicitlyRenamedIfFieldShouldExtractValueFromIdField() { } @Test // DATAMONGO-1050 - public void annotatedIdFieldShouldExtractValueFromUnderscoreIdField() { + void annotatedIdFieldShouldExtractValueFromUnderscoreIdField() { org.bson.Document document = new org.bson.Document().append("_id", "A").append("id", "B"); @@ -1676,7 +1678,7 @@ public void annotatedIdFieldShouldExtractValueFromUnderscoreIdField() { } @Test // DATAMONGO-1102 - public void convertsJava8DateTimeTypesToDateAndBack() { + void convertsJava8DateTimeTypesToDateAndBack() { TypeWithLocalDateTime source = new TypeWithLocalDateTime(); LocalDateTime reference = source.date; @@ -1690,7 +1692,7 @@ public void convertsJava8DateTimeTypesToDateAndBack() { } @Test // DATAMONGO-1128 - public void writesOptionalsCorrectly() { + void writesOptionalsCorrectly() { TypeWithOptional type = new TypeWithOptional(); type.localDateTime = Optional.of(LocalDateTime.now()); @@ -1706,8 +1708,8 @@ public void writesOptionalsCorrectly() { } @Test // DATAMONGO-1128 - @Ignore("Broken by DATAMONGO-1992 - In fact, storing Optional fields seems an anti-pattern.") - public void readsOptionalsCorrectly() { + @Disabled("Broken by DATAMONGO-1992 - In fact, storing Optional fields seems an anti-pattern.") + void readsOptionalsCorrectly() { LocalDateTime now = LocalDateTime.now(); Date reference = Date.from(now.atZone(systemDefault()).toInstant()); @@ -1722,7 +1724,7 @@ public void readsOptionalsCorrectly() { } @Test // DATAMONGO-1118 - public void convertsMapKeyUsingCustomConverterForAndBackwards() { + void convertsMapKeyUsingCustomConverterForAndBackwards() { MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext); converter.setCustomConversions( @@ -1740,7 +1742,7 @@ public void convertsMapKeyUsingCustomConverterForAndBackwards() { } @Test // DATAMONGO-1118 - public void writesMapKeyUsingCustomConverter() { + void writesMapKeyUsingCustomConverter() { MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext); converter.setCustomConversions(new MongoCustomConversions(Arrays.asList(new FooBarEnumToStringConverter()))); @@ -1761,7 +1763,7 @@ public void writesMapKeyUsingCustomConverter() { } @Test // DATAMONGO-1118 - public void readsMapKeyUsingCustomConverter() { + void readsMapKeyUsingCustomConverter() { MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext); converter.setCustomConversions(new MongoCustomConversions(Arrays.asList(new StringToFooNumConverter()))); @@ -1775,12 +1777,12 @@ public void readsMapKeyUsingCustomConverter() { } @Test // DATAMONGO-1471 - public void readsDocumentWithPrimitiveIdButNoValue() { + void readsDocumentWithPrimitiveIdButNoValue() { assertThat(converter.read(ClassWithIntId.class, new org.bson.Document())).isNotNull(); } @Test // DATAMONGO-1497 - public void readsPropertyFromNestedFieldCorrectly() { + void readsPropertyFromNestedFieldCorrectly() { org.bson.Document source = new org.bson.Document("nested", new org.bson.Document("sample", "value")); TypeWithPropertyInNestedField result = converter.read(TypeWithPropertyInNestedField.class, source); @@ -1789,7 +1791,7 @@ public void readsPropertyFromNestedFieldCorrectly() { } @Test // DATAMONGO-1525 - public void readsEmptyEnumSet() { + void readsEmptyEnumSet() { org.bson.Document source = new org.bson.Document("enumSet", Collections.emptyList()); @@ -1797,7 +1799,7 @@ public void readsEmptyEnumSet() { } @Test // DATAMONGO-1757 - public void failsReadingDocumentIntoSimpleType() { + void failsReadingDocumentIntoSimpleType() { org.bson.Document nested = new org.bson.Document("key", "value"); org.bson.Document source = new org.bson.Document("map", new org.bson.Document("key", nested)); @@ -1807,7 +1809,7 @@ public void failsReadingDocumentIntoSimpleType() { } @Test // DATAMONGO-1831 - public void shouldConvertArrayInConstructorCorrectly() { + void shouldConvertArrayInConstructorCorrectly() { org.bson.Document source = new org.bson.Document("array", Collections.emptyList()); @@ -1815,7 +1817,7 @@ public void shouldConvertArrayInConstructorCorrectly() { } @Test // DATAMONGO-1831 - public void shouldConvertNullForArrayInConstructorCorrectly() { + void shouldConvertNullForArrayInConstructorCorrectly() { org.bson.Document source = new org.bson.Document(); @@ -1823,7 +1825,7 @@ public void shouldConvertNullForArrayInConstructorCorrectly() { } @Test // DATAMONGO-1898 - public void writesInterfaceBackedEnumsToSimpleNameByDefault() { + void writesInterfaceBackedEnumsToSimpleNameByDefault() { org.bson.Document document = new org.bson.Document(); @@ -1839,7 +1841,7 @@ public void writesInterfaceBackedEnumsToSimpleNameByDefault() { } @Test // DATAMONGO-1898 - public void rejectsConversionFromStringToEnumBackedInterface() { + void rejectsConversionFromStringToEnumBackedInterface() { org.bson.Document document = new org.bson.Document("property", InterfacedEnum.INSTANCE.name()); @@ -1848,7 +1850,7 @@ public void rejectsConversionFromStringToEnumBackedInterface() { } @Test // DATAMONGO-1898 - public void readsInterfacedEnumIfConverterIsRegistered() { + void readsInterfacedEnumIfConverterIsRegistered() { org.bson.Document document = new org.bson.Document("property", InterfacedEnum.INSTANCE.name()); @@ -1869,7 +1871,7 @@ public SomeInterface convert(String source) { } @Test // DATAMONGO-1904 - public void readsNestedArraysCorrectly() { + void readsNestedArraysCorrectly() { List>> floats = Arrays.asList(Arrays.asList(Arrays.asList(1.0f, 2.0f))); @@ -1882,7 +1884,7 @@ public void readsNestedArraysCorrectly() { } @Test // DATAMONGO-1992 - public void readsImmutableObjectCorrectly() { + void readsImmutableObjectCorrectly() { org.bson.Document document = new org.bson.Document("_id", "foo"); @@ -1893,7 +1895,7 @@ public void readsImmutableObjectCorrectly() { } @Test // DATAMONGO-2026 - public void readsImmutableObjectWithConstructorIdPropertyCorrectly() { + void readsImmutableObjectWithConstructorIdPropertyCorrectly() { org.bson.Document source = new org.bson.Document("_id", "spring").append("value", "data"); @@ -1905,7 +1907,7 @@ public void readsImmutableObjectWithConstructorIdPropertyCorrectly() { } @Test // DATAMONGO-2011 - public void readsNestedListsToObjectCorrectly() { + void readsNestedListsToObjectCorrectly() { List values = Arrays.asList("ONE", "TWO"); org.bson.Document source = new org.bson.Document("value", Collections.singletonList(values)); @@ -1914,7 +1916,7 @@ public void readsNestedListsToObjectCorrectly() { } @Test // DATAMONGO-2043 - public void omitsTypeHintWhenWritingSimpleTypes() { + void omitsTypeHintWhenWritingSimpleTypes() { org.bson.Document target = new org.bson.Document(); converter.write(new org.bson.Document("value", "FitzChivalry"), target); @@ -1923,28 +1925,28 @@ public void omitsTypeHintWhenWritingSimpleTypes() { } @Test // DATAMONGO-1798 - public void convertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsObjectId() { + void convertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsObjectId() { ObjectId source = new ObjectId(); assertThat(converter.convertId(source.toHexString(), ObjectId.class)).isEqualTo(source); } @Test // DATAMONGO-1798 - public void donNotConvertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsString() { + void donNotConvertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsString() { ObjectId source = new ObjectId(); assertThat(converter.convertId(source.toHexString(), String.class)).isEqualTo(source.toHexString()); } @Test // DATAMONGO-1798 - public void donNotConvertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsObject() { + void donNotConvertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsObject() { ObjectId source = new ObjectId(); assertThat(converter.convertId(source.toHexString(), Object.class)).isEqualTo(source.toHexString()); } @Test // DATAMONGO-2135 - public void addsEqualObjectsToCollection() { + void addsEqualObjectsToCollection() { org.bson.Document itemDocument = new org.bson.Document("itemKey", "123"); org.bson.Document orderDocument = new org.bson.Document("items", @@ -1956,7 +1958,7 @@ public void addsEqualObjectsToCollection() { } @Test // DATAMONGO-1849 - public void mapsValueToExplicitTargetType() { + void mapsValueToExplicitTargetType() { WithExplicitTargetTypes source = new WithExplicitTargetTypes(); source.script = "if (a > b) a else b"; @@ -1968,7 +1970,7 @@ public void mapsValueToExplicitTargetType() { } @Test // DATAMONGO-2328 - public void readsScriptAsStringWhenAnnotatedWithFieldTargetType() { + void readsScriptAsStringWhenAnnotatedWithFieldTargetType() { String reference = "if (a > b) a else b"; WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class, @@ -1978,7 +1980,7 @@ public void readsScriptAsStringWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-1849 - public void mapsCollectionValueToExplicitTargetType() { + void mapsCollectionValueToExplicitTargetType() { String script = "if (a > b) a else b"; WithExplicitTargetTypes source = new WithExplicitTargetTypes(); @@ -1991,7 +1993,7 @@ public void mapsCollectionValueToExplicitTargetType() { } @Test // DATAMONGO-1849 - public void mapsBigDecimalToDecimal128WhenAnnotatedWithFieldTargetType() { + void mapsBigDecimalToDecimal128WhenAnnotatedWithFieldTargetType() { WithExplicitTargetTypes source = new WithExplicitTargetTypes(); source.bigDecimal = BigDecimal.valueOf(3.14159D); @@ -2003,7 +2005,7 @@ public void mapsBigDecimalToDecimal128WhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void mapsDateToLongWhenAnnotatedWithFieldTargetType() { + void mapsDateToLongWhenAnnotatedWithFieldTargetType() { WithExplicitTargetTypes source = new WithExplicitTargetTypes(); source.dateAsLong = new Date(); @@ -2015,7 +2017,7 @@ public void mapsDateToLongWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void readsLongAsDateWhenAnnotatedWithFieldTargetType() { + void readsLongAsDateWhenAnnotatedWithFieldTargetType() { Date reference = new Date(); WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class, @@ -2025,7 +2027,7 @@ public void readsLongAsDateWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void mapsLongToDateWhenAnnotatedWithFieldTargetType() { + void mapsLongToDateWhenAnnotatedWithFieldTargetType() { Date date = new Date(); WithExplicitTargetTypes source = new WithExplicitTargetTypes(); @@ -2038,7 +2040,7 @@ public void mapsLongToDateWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void readsDateAsLongWhenAnnotatedWithFieldTargetType() { + void readsDateAsLongWhenAnnotatedWithFieldTargetType() { Date reference = new Date(); WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class, @@ -2048,7 +2050,7 @@ public void readsDateAsLongWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void mapsStringAsBooleanWhenAnnotatedWithFieldTargetType() { + void mapsStringAsBooleanWhenAnnotatedWithFieldTargetType() { WithExplicitTargetTypes source = new WithExplicitTargetTypes(); source.stringAsBoolean = "true"; @@ -2060,7 +2062,7 @@ public void mapsStringAsBooleanWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void readsBooleanAsStringWhenAnnotatedWithFieldTargetType() { + void readsBooleanAsStringWhenAnnotatedWithFieldTargetType() { WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class, new org.bson.Document("stringAsBoolean", true)); @@ -2069,7 +2071,7 @@ public void readsBooleanAsStringWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void mapsDateAsObjectIdWhenAnnotatedWithFieldTargetType() { + void mapsDateAsObjectIdWhenAnnotatedWithFieldTargetType() { WithExplicitTargetTypes source = new WithExplicitTargetTypes(); source.dateAsObjectId = new Date(); @@ -2083,7 +2085,7 @@ public void mapsDateAsObjectIdWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2328 - public void readsObjectIdAsDateWhenAnnotatedWithFieldTargetType() { + void readsObjectIdAsDateWhenAnnotatedWithFieldTargetType() { ObjectId reference = new ObjectId(); WithExplicitTargetTypes target = converter.read(WithExplicitTargetTypes.class, @@ -2093,7 +2095,7 @@ public void readsObjectIdAsDateWhenAnnotatedWithFieldTargetType() { } @Test // DATAMONGO-2410 - public void shouldAllowReadingBackDbObject() { + void shouldAllowReadingBackDbObject() { assertThat(converter.read(BasicDBObject.class, new org.bson.Document("property", "value"))) .isEqualTo(new BasicDBObject("property", "value")); @@ -2150,7 +2152,7 @@ static class Person implements Contact { Set
      addresses; - public Person() { + Person() { } @@ -2207,7 +2209,7 @@ static class A { String valueType; T value; - public A(T value) { + A(T value) { this.valueType = value.getClass().getName(); this.value = value; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java index bd1723b8bb..0f60969909 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersUnitTests.java @@ -28,7 +28,8 @@ import org.assertj.core.data.TemporalUnitLessThanOffset; import org.bson.BsonTimestamp; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; + import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.geo.Box; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java index 0d0f2cd494..85afdb36f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoCustomConversionsUnitTests.java @@ -21,7 +21,8 @@ import java.util.Collections; import java.util.Date; -import org.junit.Test; +import org.junit.jupiter.api.Test; + import org.springframework.core.convert.converter.Converter; /** @@ -29,10 +30,10 @@ * * @author Christoph Strobl */ -public class MongoCustomConversionsUnitTests { +class MongoCustomConversionsUnitTests { @Test // DATAMONGO-2349 - public void nonAnnotatedConverterForJavaTimeTypeShouldOnlyBeRegisteredAsReadingConverter() { + void nonAnnotatedConverterForJavaTimeTypeShouldOnlyBeRegisteredAsReadingConverter() { MongoCustomConversions conversions = new MongoCustomConversions( Collections.singletonList(new DateToZonedDateTimeConverter())); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java index 30ab0ab093..7c069a5b81 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java @@ -27,11 +27,11 @@ import java.util.regex.Pattern; import org.bson.conversions.Bson; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Example; @@ -52,7 +52,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MongoExampleMapperUnitTests { MongoExampleMapper mapper; @@ -61,7 +61,7 @@ public class MongoExampleMapperUnitTests { @Mock MongoDatabaseFactory factory; - @Before + @BeforeEach public void setUp() { this.context = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java index 9f9b385dd6..a973558bc4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapperUnitTests.java @@ -23,8 +23,8 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -105,7 +105,7 @@ public class MongoJsonSchemaMapperUnitTests { " }" + // " } }"; - @Before + @BeforeEach public void setUp() { mapper = new MongoJsonSchemaMapper(new MappingMongoConverter(mock(DbRefResolver.class), new MongoMappingContext())); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java index cce1995069..15270484c5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/NamedMongoScriptConvertsUnitTests.java @@ -19,7 +19,7 @@ import org.bson.Document; import org.bson.types.Code; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java index f3130518cb..145c008eff 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ObjectPathUnitTests.java @@ -18,8 +18,8 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -36,7 +36,7 @@ public class ObjectPathUnitTests { MongoPersistentEntity two; MongoPersistentEntity three; - @Before + @BeforeEach public void setUp() { one = new BasicMongoPersistentEntity<>(ClassTypeInformation.from(EntityOne.class)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java index 9fa5e84de2..e2823a4df0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/TermToStringConverterUnitTests.java @@ -17,7 +17,7 @@ import static org.mockito.Mockito.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.convert.MongoConverters.TermToStringConverter; import org.springframework.data.mongodb.core.query.Term; import org.springframework.data.mongodb.core.query.Term.Type; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index 01eddc0268..20a2c231e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -31,12 +31,12 @@ import java.util.concurrent.atomic.AtomicInteger; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; @@ -66,19 +66,19 @@ * @author Mark Paluch * @author Pavel Vodrazka */ -@RunWith(MockitoJUnitRunner.class) -public class UpdateMapperUnitTests { +@ExtendWith(MockitoExtension.class) +class UpdateMapperUnitTests { @Mock MongoDatabaseFactory factory; - MappingMongoConverter converter; - MongoMappingContext context; - UpdateMapper mapper; + private MappingMongoConverter converter; + private MongoMappingContext context; + private UpdateMapper mapper; private Converter writingConverterSpy; - @Before + @BeforeEach @SuppressWarnings("unchecked") - public void setUp() { + void setUp() { this.writingConverterSpy = Mockito.spy(new NestedEntityWriteConverter()); CustomConversions conversions = new MongoCustomConversions(Collections.singletonList(writingConverterSpy)); @@ -95,7 +95,7 @@ public void setUp() { } @Test // DATAMONGO-721 - public void updateMapperRetainsTypeInformationForCollectionField() { + void updateMapperRetainsTypeInformationForCollectionField() { Update update = new Update().push("list", new ConcreteChildClass("2", "BAR")); @@ -109,7 +109,7 @@ public void updateMapperRetainsTypeInformationForCollectionField() { } @Test // DATAMONGO-807 - public void updateMapperShouldRetainTypeInformationForNestedEntities() { + void updateMapperShouldRetainTypeInformationForNestedEntities() { Update update = Update.update("model", new ModelImpl(1)); UpdateMapper mapper = new UpdateMapper(converter); @@ -123,7 +123,7 @@ public void updateMapperShouldRetainTypeInformationForNestedEntities() { } @Test // DATAMONGO-807 - public void updateMapperShouldNotPersistTypeInformationForKnownSimpleTypes() { + void updateMapperShouldNotPersistTypeInformationForKnownSimpleTypes() { Update update = Update.update("model.value", 1); UpdateMapper mapper = new UpdateMapper(converter); @@ -136,7 +136,7 @@ public void updateMapperShouldNotPersistTypeInformationForKnownSimpleTypes() { } @Test // DATAMONGO-807 - public void updateMapperShouldNotPersistTypeInformationForNullValues() { + void updateMapperShouldNotPersistTypeInformationForNullValues() { Update update = Update.update("model", null); UpdateMapper mapper = new UpdateMapper(converter); @@ -149,7 +149,7 @@ public void updateMapperShouldNotPersistTypeInformationForNullValues() { } @Test // DATAMONGO-407 - public void updateMapperShouldRetainTypeInformationForNestedCollectionElements() { + void updateMapperShouldRetainTypeInformationForNestedCollectionElements() { Update update = Update.update("list.$", new ConcreteChildClass("42", "bubu")); @@ -163,7 +163,7 @@ public void updateMapperShouldRetainTypeInformationForNestedCollectionElements() } @Test // DATAMONGO-407 - public void updateMapperShouldSupportNestedCollectionElementUpdates() { + void updateMapperShouldSupportNestedCollectionElementUpdates() { Update update = Update.update("list.$.value", "foo").set("list.$.otherValue", "bar"); @@ -177,7 +177,7 @@ public void updateMapperShouldSupportNestedCollectionElementUpdates() { } @Test // DATAMONGO-407 - public void updateMapperShouldWriteTypeInformationForComplexNestedCollectionElementUpdates() { + void updateMapperShouldWriteTypeInformationForComplexNestedCollectionElementUpdates() { Update update = Update.update("list.$.value", "foo").set("list.$.someObject", new ConcreteChildClass("42", "bubu")); @@ -195,7 +195,7 @@ public void updateMapperShouldWriteTypeInformationForComplexNestedCollectionElem @SuppressWarnings({ "unchecked", "rawtypes" }) @Test // DATAMONGO-812 - public void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingSimpleTypes() { + void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingSimpleTypes() { Update update = new Update().push("values").each("spring", "data", "mongodb"); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Model.class)); @@ -211,7 +211,7 @@ public void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingSimpleT } @Test // DATAMONGO-812 - public void updateMapperShouldConvertPushWhithoutAddingClassInformationWhenUsedWithEvery() { + void updateMapperShouldConvertPushWhithoutAddingClassInformationWhenUsedWithEvery() { Update update = new Update().push("values").each("spring", "data", "mongodb"); @@ -225,7 +225,7 @@ public void updateMapperShouldConvertPushWhithoutAddingClassInformationWhenUsedW @SuppressWarnings({ "unchecked", "rawtypes" }) @Test // DATAMONGO-812 - public void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingCustomTypes() { + void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingCustomTypes() { Update update = new Update().push("models").each(new ListModel("spring", "data", "mongodb")); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -240,7 +240,7 @@ public void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingCustomT } @Test // DATAMONGO-812 - public void updateMapperShouldRetainClassInformationForPushCorrectlyWhenCalledWithEachUsingCustomTypes() { + void updateMapperShouldRetainClassInformationForPushCorrectlyWhenCalledWithEachUsingCustomTypes() { Update update = new Update().push("models").each(new ListModel("spring", "data", "mongodb")); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -254,7 +254,7 @@ public void updateMapperShouldRetainClassInformationForPushCorrectlyWhenCalledWi } @Test // DATAMONGO-812 - public void testUpdateShouldAllowMultiplePushEachForDifferentFields() { + void testUpdateShouldAllowMultiplePushEachForDifferentFields() { Update update = new Update().push("category").each("spring", "data").push("type").each("mongodb"); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class)); @@ -265,7 +265,7 @@ public void testUpdateShouldAllowMultiplePushEachForDifferentFields() { } @Test // DATAMONGO-943 - public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositiveIndexParameter() { + void updatePushEachAtPositionWorksCorrectlyWhenGivenPositiveIndexParameter() { Update update = new Update().push("key").atPosition(2).each(Arrays.asList("Arya", "Arry", "Weasel")); @@ -280,7 +280,7 @@ public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositiveIndexParamete } @Test // DATAMONGO-943, DATAMONGO-2055 - public void updatePushEachAtNegativePositionWorksCorrectly() { + void updatePushEachAtNegativePositionWorksCorrectly() { Update update = new Update().push("key").atPosition(-2).each(Arrays.asList("Arya", "Arry", "Weasel")); @@ -294,7 +294,7 @@ public void updatePushEachAtNegativePositionWorksCorrectly() { } @Test // DATAMONGO-943 - public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionFirst() { + void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionFirst() { Update update = new Update().push("key").atPosition(Position.FIRST).each(Arrays.asList("Arya", "Arry", "Weasel")); @@ -309,7 +309,7 @@ public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionFirst() { } @Test // DATAMONGO-943 - public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionLast() { + void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionLast() { Update update = new Update().push("key").atPosition(Position.LAST).each(Arrays.asList("Arya", "Arry", "Weasel")); @@ -323,7 +323,7 @@ public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionLast() { } @Test // DATAMONGO-943 - public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionNull() { + void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionNull() { Update update = new Update().push("key").atPosition(null).each(Arrays.asList("Arya", "Arry", "Weasel")); @@ -337,7 +337,7 @@ public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionNull() { } @Test // DATAMONGO-832 - public void updatePushEachWithSliceShouldRenderCorrectly() { + void updatePushEachWithSliceShouldRenderCorrectly() { Update update = new Update().push("key").slice(5).each(Arrays.asList("Arya", "Arry", "Weasel")); @@ -351,7 +351,7 @@ public void updatePushEachWithSliceShouldRenderCorrectly() { } @Test // DATAMONGO-832 - public void updatePushEachWithSliceShouldRenderWhenUsingMultiplePushCorrectly() { + void updatePushEachWithSliceShouldRenderWhenUsingMultiplePushCorrectly() { Update update = new Update().push("key").slice(5).each(Arrays.asList("Arya", "Arry", "Weasel")).push("key-2") .slice(-2).each("The Beggar King", "Viserys III Targaryen"); @@ -371,7 +371,7 @@ public void updatePushEachWithSliceShouldRenderWhenUsingMultiplePushCorrectly() } @Test // DATAMONGO-1141 - public void updatePushEachWithValueSortShouldRenderCorrectly() { + void updatePushEachWithValueSortShouldRenderCorrectly() { Update update = new Update().push("scores").sort(Direction.DESC).each(42, 23, 68); @@ -387,7 +387,7 @@ public void updatePushEachWithValueSortShouldRenderCorrectly() { } @Test // DATAMONGO-1141 - public void updatePushEachWithDocumentSortShouldRenderCorrectly() { + void updatePushEachWithDocumentSortShouldRenderCorrectly() { Update update = new Update().push("list") .sort(Sort.by(new Order(Direction.ASC, "value"), new Order(Direction.ASC, "field"))) @@ -405,7 +405,7 @@ public void updatePushEachWithDocumentSortShouldRenderCorrectly() { } @Test // DATAMONGO-1141 - public void updatePushEachWithSortShouldRenderCorrectlyWhenUsingMultiplePush() { + void updatePushEachWithSortShouldRenderCorrectlyWhenUsingMultiplePush() { Update update = new Update().push("authors").sort(Direction.ASC).each("Harry").push("chapters") .sort(Sort.by(Direction.ASC, "order")).each(Collections.emptyList()); @@ -427,7 +427,7 @@ public void updatePushEachWithSortShouldRenderCorrectlyWhenUsingMultiplePush() { } @Test // DATAMONGO-410 - public void testUpdateMapperShouldConsiderCustomWriteTarget() { + void testUpdateMapperShouldConsiderCustomWriteTarget() { List someValues = Arrays.asList(new NestedEntity("spring"), new NestedEntity("data"), new NestedEntity("mongodb")); @@ -440,7 +440,7 @@ public void testUpdateMapperShouldConsiderCustomWriteTarget() { } @Test // DATAMONGO-404 - public void createsDbRefForEntityIdOnPulls() { + void createsDbRefForEntityIdOnPulls() { Update update = new Update().pull("dbRefAnnotatedList.id", "2"); @@ -452,7 +452,7 @@ public void createsDbRefForEntityIdOnPulls() { } @Test // DATAMONGO-404 - public void createsDbRefForEntityOnPulls() { + void createsDbRefForEntityOnPulls() { Entity entity = new Entity(); entity.id = "5"; @@ -465,15 +465,16 @@ public void createsDbRefForEntityOnPulls() { assertThat(pullClause.get("dbRefAnnotatedList")).isEqualTo(new DBRef("entity", entity.id)); } - @Test(expected = MappingException.class) // DATAMONGO-404 - public void rejectsInvalidFieldReferenceForDbRef() { + @Test // DATAMONGO-404 + void rejectsInvalidFieldReferenceForDbRef() { Update update = new Update().pull("dbRefAnnotatedList.name", "NAME"); - mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(DocumentWithDBRefCollection.class)); + assertThatThrownBy(() -> mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(DocumentWithDBRefCollection.class))).isInstanceOf(MappingException.class); } @Test // DATAMONGO-404 - public void rendersNestedDbRefCorrectly() { + void rendersNestedDbRefCorrectly() { Update update = new Update().pull("nested.dbRefAnnotatedList.id", "2"); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -484,7 +485,7 @@ public void rendersNestedDbRefCorrectly() { } @Test // DATAMONGO-468 - public void rendersUpdateOfDbRefPropertyWithDomainObjectCorrectly() { + void rendersUpdateOfDbRefPropertyWithDomainObjectCorrectly() { Entity entity = new Entity(); entity.id = "5"; @@ -498,7 +499,7 @@ public void rendersUpdateOfDbRefPropertyWithDomainObjectCorrectly() { } @Test // DATAMONGO-862 - public void rendersUpdateAndPreservesKeyForPathsNotPointingToProperty() { + void rendersUpdateAndPreservesKeyForPathsNotPointingToProperty() { Update update = new Update().set("listOfInterface.$.value", "expected-value"); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -509,7 +510,7 @@ public void rendersUpdateAndPreservesKeyForPathsNotPointingToProperty() { } @Test // DATAMONGO-863 - public void doesNotConvertRawDocuments() { + void doesNotConvertRawDocuments() { Update update = new Update(); update.pull("options", @@ -528,7 +529,7 @@ public void doesNotConvertRawDocuments() { @SuppressWarnings({ "unchecked", "rawtypes" }) @Test // DATAMONG0-471 - public void testUpdateShouldApply$addToSetCorrectlyWhenUsedWith$each() { + void testUpdateShouldApply$addToSetCorrectlyWhenUsedWith$each() { Update update = new Update().addToSet("values").each("spring", "data", "mongodb"); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -542,7 +543,7 @@ public void doesNotConvertRawDocuments() { } @Test // DATAMONG0-471 - public void testUpdateShouldRetainClassTypeInformationWhenUsing$addToSetWith$eachForCustomTypes() { + void testUpdateShouldRetainClassTypeInformationWhenUsing$addToSetWith$eachForCustomTypes() { Update update = new Update().addToSet("models").each(new ModelImpl(2014), new ModelImpl(1), new ModelImpl(28)); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -559,7 +560,7 @@ public void doesNotConvertRawDocuments() { } @Test // DATAMONGO-897 - public void updateOnDbrefPropertyOfInterfaceTypeWithoutExplicitGetterForIdShouldBeMappedCorrectly() { + void updateOnDbrefPropertyOfInterfaceTypeWithoutExplicitGetterForIdShouldBeMappedCorrectly() { Update update = new Update().set("referencedDocument", new InterfaceDocumentDefinitionImpl("1", "Foo")); Document mappedObject = mapper.getMappedObject(update.getUpdateObject(), @@ -573,7 +574,7 @@ public void updateOnDbrefPropertyOfInterfaceTypeWithoutExplicitGetterForIdShould } @Test // DATAMONGO-847 - public void updateMapperConvertsNestedQueryCorrectly() { + void updateMapperConvertsNestedQueryCorrectly() { Update update = new Update().pull("list", Query.query(Criteria.where("value").in("foo", "bar"))); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -588,7 +589,7 @@ public void updateMapperConvertsNestedQueryCorrectly() { } @Test // DATAMONGO-847 - public void updateMapperConvertsPullWithNestedQuerfyOnDBRefCorrectly() { + void updateMapperConvertsPullWithNestedQuerfyOnDBRefCorrectly() { Update update = new Update().pull("dbRefAnnotatedList", Query.query(Criteria.where("id").is("1"))); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -601,7 +602,7 @@ public void updateMapperConvertsPullWithNestedQuerfyOnDBRefCorrectly() { } @Test // DATAMONGO-1077 - public void shouldNotRemovePositionalParameter() { + void shouldNotRemovePositionalParameter() { Update update = new Update(); update.unset("dbRefAnnotatedList.$"); @@ -615,7 +616,7 @@ public void shouldNotRemovePositionalParameter() { } @Test // DATAMONGO-1210 - public void mappingEachOperatorShouldNotAddTypeInfoForNonInterfaceNonAbstractTypes() { + void mappingEachOperatorShouldNotAddTypeInfoForNonInterfaceNonAbstractTypes() { Update update = new Update().addToSet("nestedDocs").each(new NestedDocument("nested-1"), new NestedDocument("nested-2")); @@ -628,7 +629,7 @@ public void mappingEachOperatorShouldNotAddTypeInfoForNonInterfaceNonAbstractTyp } @Test // DATAMONGO-1210 - public void mappingEachOperatorShouldAddTypeHintForInterfaceTypes() { + void mappingEachOperatorShouldAddTypeHintForInterfaceTypes() { Update update = new Update().addToSet("models").each(new ModelImpl(1), new ModelImpl(2)); @@ -640,7 +641,7 @@ public void mappingEachOperatorShouldAddTypeHintForInterfaceTypes() { } @Test // DATAMONGO-1210 - public void mappingEachOperatorShouldAddTypeHintForAbstractTypes() { + void mappingEachOperatorShouldAddTypeHintForAbstractTypes() { Update update = new Update().addToSet("list").each(new ConcreteChildClass("foo", "one"), new ConcreteChildClass("bar", "two")); @@ -653,7 +654,7 @@ public void mappingEachOperatorShouldAddTypeHintForAbstractTypes() { } @Test // DATAMONGO-1210 - public void mappingShouldOnlyRemoveTypeHintFromTopLevelTypeInCaseOfNestedDocument() { + void mappingShouldOnlyRemoveTypeHintFromTopLevelTypeInCaseOfNestedDocument() { WrapperAroundInterfaceType wait = new WrapperAroundInterfaceType(); wait.interfaceType = new ModelImpl(1); @@ -670,7 +671,7 @@ public void mappingShouldOnlyRemoveTypeHintFromTopLevelTypeInCaseOfNestedDocumen } @Test // DATAMONGO-1210 - public void mappingShouldRetainTypeInformationOfNestedListWhenUpdatingConcreteyParentType() { + void mappingShouldRetainTypeInformationOfNestedListWhenUpdatingConcreteyParentType() { ListModelWrapper lmw = new ListModelWrapper(); lmw.models = Collections.singletonList(new ModelImpl(1)); @@ -685,7 +686,7 @@ public void mappingShouldRetainTypeInformationOfNestedListWhenUpdatingConcreteyP } @Test // DATAMONGO-1809 - public void pathShouldIdentifyPositionalParameterWithMoreThanOneDigit() { + void pathShouldIdentifyPositionalParameterWithMoreThanOneDigit() { Document at2digitPosition = mapper.getMappedObject(new Update() .addToSet("concreteInnerList.10.concreteTypeList", new SomeInterfaceImpl("szeth")).getUpdateObject(), @@ -702,7 +703,7 @@ public void pathShouldIdentifyPositionalParameterWithMoreThanOneDigit() { } @Test // DATAMONGO-1236 - public void mappingShouldRetainTypeInformationForObjectValues() { + void mappingShouldRetainTypeInformationForObjectValues() { Update update = new Update().set("value", new NestedDocument("kaladin")); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -713,7 +714,7 @@ public void mappingShouldRetainTypeInformationForObjectValues() { } @Test // DATAMONGO-1236 - public void mappingShouldNotRetainTypeInformationForConcreteValues() { + void mappingShouldNotRetainTypeInformationForConcreteValues() { Update update = new Update().set("concreteValue", new NestedDocument("shallan")); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -724,7 +725,7 @@ public void mappingShouldNotRetainTypeInformationForConcreteValues() { } @Test // DATAMONGO-1236 - public void mappingShouldRetainTypeInformationForObjectValuesWithAlias() { + void mappingShouldRetainTypeInformationForObjectValuesWithAlias() { Update update = new Update().set("value", new NestedDocument("adolin")); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -735,7 +736,7 @@ public void mappingShouldRetainTypeInformationForObjectValuesWithAlias() { } @Test // DATAMONGO-1236 - public void mappingShouldRetrainTypeInformationWhenValueTypeOfMapDoesNotMatchItsDeclaration() { + void mappingShouldRetrainTypeInformationWhenValueTypeOfMapDoesNotMatchItsDeclaration() { Map map = Collections.singletonMap("szeth", new NestedDocument("son-son-vallano")); @@ -748,7 +749,7 @@ public void mappingShouldRetrainTypeInformationWhenValueTypeOfMapDoesNotMatchIts } @Test // DATAMONGO-1236 - public void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDeclaration() { + void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDeclaration() { Map map = Collections.singletonMap("jasnah", new NestedDocument("kholin")); @@ -762,7 +763,7 @@ public void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDecla @Test // DATAMONGO-1250 @SuppressWarnings("unchecked") - public void mapsUpdateWithBothReadingAndWritingConverterRegistered() { + void mapsUpdateWithBothReadingAndWritingConverterRegistered() { CustomConversions conversions = new MongoCustomConversions(Arrays.asList( ClassWithEnum.AllocationToStringConverter.INSTANCE, ClassWithEnum.StringToAllocationConverter.INSTANCE)); @@ -785,7 +786,7 @@ public void mapsUpdateWithBothReadingAndWritingConverterRegistered() { } @Test // DATAMONGO-1251 - public void mapsNullValueCorrectlyForSimpleTypes() { + void mapsNullValueCorrectlyForSimpleTypes() { Update update = new Update().set("value", null); @@ -797,7 +798,7 @@ public void mapsNullValueCorrectlyForSimpleTypes() { } @Test // DATAMONGO-1251 - public void mapsNullValueCorrectlyForJava8Date() { + void mapsNullValueCorrectlyForJava8Date() { Update update = new Update().set("date", null); @@ -809,7 +810,7 @@ public void mapsNullValueCorrectlyForJava8Date() { } @Test // DATAMONGO-1251 - public void mapsNullValueCorrectlyForCollectionTypes() { + void mapsNullValueCorrectlyForCollectionTypes() { Update update = new Update().set("values", null); @@ -821,7 +822,7 @@ public void mapsNullValueCorrectlyForCollectionTypes() { } @Test // DATAMONGO-1251 - public void mapsNullValueCorrectlyForPropertyOfNestedDocument() { + void mapsNullValueCorrectlyForPropertyOfNestedDocument() { Update update = new Update().set("concreteValue.name", null); @@ -834,7 +835,7 @@ public void mapsNullValueCorrectlyForPropertyOfNestedDocument() { } @Test // DATAMONGO-1288 - public void mapsAtomicIntegerToIntegerCorrectly() { + void mapsAtomicIntegerToIntegerCorrectly() { Update update = new Update().set("intValue", new AtomicInteger(10)); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -845,7 +846,7 @@ public void mapsAtomicIntegerToIntegerCorrectly() { } @Test // DATAMONGO-1288 - public void mapsAtomicIntegerToPrimitiveIntegerCorrectly() { + void mapsAtomicIntegerToPrimitiveIntegerCorrectly() { Update update = new Update().set("primIntValue", new AtomicInteger(10)); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -856,7 +857,7 @@ public void mapsAtomicIntegerToPrimitiveIntegerCorrectly() { } @Test // DATAMONGO-1404 - public void mapsMinCorrectly() { + void mapsMinCorrectly() { Update update = new Update().min("minfield", 10); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -866,7 +867,7 @@ public void mapsMinCorrectly() { } @Test // DATAMONGO-1404 - public void mapsMaxCorrectly() { + void mapsMaxCorrectly() { Update update = new Update().max("maxfield", 999); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -877,7 +878,7 @@ public void mapsMaxCorrectly() { @Test // DATAMONGO-1423, DATAMONGO-2155 @SuppressWarnings("unchecked") - public void mappingShouldConsiderCustomConvertersForEnumMapKeys() { + void mappingShouldConsiderCustomConvertersForEnumMapKeys() { CustomConversions conversions = new MongoCustomConversions(Arrays.asList( ClassWithEnum.AllocationToStringConverter.INSTANCE, ClassWithEnum.StringToAllocationConverter.INSTANCE)); @@ -904,7 +905,7 @@ public void mappingShouldConsiderCustomConvertersForEnumMapKeys() { } @Test // DATAMONGO-1176 - public void mappingShouldPrepareUpdateObjectForMixedOperatorsAndFields() { + void mappingShouldPrepareUpdateObjectForMixedOperatorsAndFields() { Document document = new Document("key", "value").append("$set", new Document("a", "b").append("x", "y")); @@ -915,7 +916,7 @@ public void mappingShouldPrepareUpdateObjectForMixedOperatorsAndFields() { } @Test // DATAMONGO-1176 - public void mappingShouldReturnReplaceObject() { + void mappingShouldReturnReplaceObject() { Document document = new Document("key", "value").append("a", "b").append("x", "y"); @@ -928,7 +929,7 @@ public void mappingShouldReturnReplaceObject() { } @Test // DATAMONGO-1176 - public void mappingShouldReturnUpdateObject() { + void mappingShouldReturnUpdateObject() { Document document = new Document("$push", new Document("x", "y")).append("$set", new Document("a", "b")); @@ -940,7 +941,7 @@ public void mappingShouldReturnUpdateObject() { } @Test // DATAMONGO-1486, DATAMONGO-2155 - public void mappingShouldConvertMapKeysToString() { + void mappingShouldConvertMapKeysToString() { Update update = new Update().set("map", Collections.singletonMap(25, "#StarTrek50")); Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), @@ -956,7 +957,7 @@ public void mappingShouldConvertMapKeysToString() { } @Test // DATAMONGO-1772 - public void mappingShouldAddTypeKeyInListOfInterfaceTypeContainedInConcreteObjectCorrectly() { + void mappingShouldAddTypeKeyInListOfInterfaceTypeContainedInConcreteObjectCorrectly() { ConcreteInner inner = new ConcreteInner(); inner.interfaceTypeList = Collections.singletonList(new SomeInterfaceImpl()); @@ -970,7 +971,7 @@ public void mappingShouldAddTypeKeyInListOfInterfaceTypeContainedInConcreteObjec } @Test // DATAMONGO-1772 - public void mappingShouldAddTypeKeyInListOfAbstractTypeContainedInConcreteObjectCorrectly() { + void mappingShouldAddTypeKeyInListOfAbstractTypeContainedInConcreteObjectCorrectly() { ConcreteInner inner = new ConcreteInner(); inner.abstractTypeList = Collections.singletonList(new SomeInterfaceImpl()); @@ -984,7 +985,7 @@ public void mappingShouldAddTypeKeyInListOfAbstractTypeContainedInConcreteObject } @Test // DATAMONGO-2155 - public void shouldPreserveFieldNamesOfMapProperties() { + void shouldPreserveFieldNamesOfMapProperties() { Update update = Update .fromDocument(new Document("concreteMap", new Document("Name", new Document("name", "fooo")))); @@ -996,7 +997,7 @@ public void shouldPreserveFieldNamesOfMapProperties() { } @Test // DATAMONGO-2155 - public void shouldPreserveExplicitFieldNamesInsideMapProperties() { + void shouldPreserveExplicitFieldNamesInsideMapProperties() { Update update = Update .fromDocument(new Document("map", new Document("Value", new Document("renamed-value", "fooo")))); @@ -1009,7 +1010,7 @@ public void shouldPreserveExplicitFieldNamesInsideMapProperties() { } @Test // DATAMONGO-2155 - public void shouldMapAliasedFieldNamesInMapsCorrectly() { + void shouldMapAliasedFieldNamesInMapsCorrectly() { Update update = Update .fromDocument(new Document("map", Collections.singletonMap("Value", new Document("value", "fooo")))); @@ -1022,7 +1023,7 @@ public void shouldMapAliasedFieldNamesInMapsCorrectly() { } @Test // DATAMONGO-2174 - public void mappingUpdateDocumentWithExplicitFieldNameShouldBePossible() { + void mappingUpdateDocumentWithExplicitFieldNameShouldBePossible() { Document mappedUpdate = mapper.getMappedObject(new Document("AValue", "a value"), context.getPersistentEntity(TypeWithFieldNameThatCannotBeDecapitalized.class)); @@ -1031,7 +1032,7 @@ public void mappingUpdateDocumentWithExplicitFieldNameShouldBePossible() { } @Test // DATAMONGO-2054 - public void mappingShouldAllowPositionAllParameter() { + void mappingShouldAllowPositionAllParameter() { Update update = new Update().inc("grades.$[]", 10); @@ -1042,7 +1043,7 @@ public void mappingShouldAllowPositionAllParameter() { } @Test // DATAMONGO-2054 - public void mappingShouldAllowPositionAllParameterWhenPropertyHasExplicitFieldName() { + void mappingShouldAllowPositionAllParameterWhenPropertyHasExplicitFieldName() { Update update = new Update().inc("list.$[]", 10); @@ -1053,7 +1054,7 @@ public void mappingShouldAllowPositionAllParameterWhenPropertyHasExplicitFieldNa } @Test // DATAMONGO-2215 - public void mappingShouldAllowPositionParameterWithIdentifier() { + void mappingShouldAllowPositionParameterWithIdentifier() { Update update = new Update().set("grades.$[element]", 10) // .filterArray(Criteria.where("element").gte(100)); @@ -1065,7 +1066,7 @@ public void mappingShouldAllowPositionParameterWithIdentifier() { } @Test // DATAMONGO-2215 - public void mappingShouldAllowPositionParameterWithIdentifierWhenFieldHasExplicitFieldName() { + void mappingShouldAllowPositionParameterWithIdentifierWhenFieldHasExplicitFieldName() { Update update = new Update().set("list.$[element]", 10) // .filterArray(Criteria.where("element").gte(100)); @@ -1077,7 +1078,7 @@ public void mappingShouldAllowPositionParameterWithIdentifierWhenFieldHasExplici } @Test // DATAMONGO-2215 - public void mappingShouldAllowNestedPositionParameterWithIdentifierWhenFieldHasExplicitFieldName() { + void mappingShouldAllowNestedPositionParameterWithIdentifierWhenFieldHasExplicitFieldName() { Update update = new Update().set("list.$[element].value", 10) // .filterArray(Criteria.where("element").gte(100)); @@ -1119,7 +1120,7 @@ static class InterfaceDocumentDefinitionImpl implements InterfaceDocumentDefinit @Id String id; String value; - public InterfaceDocumentDefinitionImpl(String id, String value) { + InterfaceDocumentDefinitionImpl(String id, String value) { this.id = id; this.value = value; @@ -1163,7 +1164,7 @@ interface Model {} static class ModelImpl implements Model { public int value; - public ModelImpl(int value) { + ModelImpl(int value) { this.value = value; } @@ -1188,7 +1189,7 @@ static class ListModel { List values; - public ListModel(String... values) { + ListModel(String... values) { this.values = Arrays.asList(values); } } @@ -1217,7 +1218,7 @@ static abstract class AbstractChildClass { String otherValue; AbstractChildClass someObject; - public AbstractChildClass(String id, String value) { + AbstractChildClass(String id, String value) { this.id = id; this.value = value; this.otherValue = "other_" + value; @@ -1226,7 +1227,7 @@ public AbstractChildClass(String id, String value) { static class ConcreteChildClass extends AbstractChildClass { - public ConcreteChildClass(String id, String value) { + ConcreteChildClass(String id, String value) { super(id, value); } } @@ -1242,7 +1243,7 @@ public List getCollectionOfNestedEntities() { static class NestedEntity { String name; - public NestedEntity(String name) { + NestedEntity(String name) { super(); this.name = name; } @@ -1288,7 +1289,7 @@ static class NestedDocument { String name; - public NestedDocument(String name) { + NestedDocument(String name) { super(); this.name = name; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java index d2e856d33a..f9d42e9fd8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java @@ -28,6 +28,7 @@ import org.junit.Before; 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.geo.Box; @@ -41,7 +42,6 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.TestEntities; import org.springframework.data.mongodb.core.Venue; -import org.springframework.data.mongodb.core.geo.GeoJsonTests.Venue2DSphere; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java index 32c6287dac..7afbf44b2d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonModuleUnitTests.java @@ -20,8 +20,8 @@ import java.io.IOException; import java.util.Arrays; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.data.geo.Point; @@ -36,7 +36,7 @@ public class GeoJsonModuleUnitTests { ObjectMapper mapper; - @Before + @BeforeEach public void setUp() { mapper = new ObjectMapper(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java index ffb7598bc3..315d9fcdec 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexFieldUnitTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort.Direction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java index 2e0dfddcb7..5ff219f652 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java @@ -21,7 +21,7 @@ import java.util.Arrays; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort.Direction; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index 78d614d6e4..0e2185fc14 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -22,12 +22,15 @@ import java.util.Date; import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + import org.springframework.dao.DataAccessException; import org.springframework.data.geo.Point; import org.springframework.data.mapping.context.MappingContextEvent; @@ -55,7 +58,8 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class MongoPersistentEntityIndexCreatorUnitTests { private @Mock MongoDatabaseFactory factory; @@ -63,12 +67,12 @@ public class MongoPersistentEntityIndexCreatorUnitTests { private @Mock MongoCollection collection; private MongoTemplate mongoTemplate; - ArgumentCaptor keysCaptor; - ArgumentCaptor optionsCaptor; - ArgumentCaptor collectionCaptor; + private ArgumentCaptor keysCaptor; + private ArgumentCaptor optionsCaptor; + private ArgumentCaptor collectionCaptor; - @Before - public void setUp() { + @BeforeEach + void setUp() { keysCaptor = ArgumentCaptor.forClass(org.bson.Document.class); optionsCaptor = ArgumentCaptor.forClass(IndexOptions.class); @@ -85,7 +89,7 @@ public void setUp() { } @Test - public void buildsIndexDefinitionUsingFieldName() { + void buildsIndexDefinitionUsingFieldName() { MongoMappingContext mappingContext = prepareMappingContext(Person.class); @@ -98,7 +102,7 @@ public void buildsIndexDefinitionUsingFieldName() { } @Test - public void doesNotCreateIndexForEntityComingFromDifferentMappingContext() { + void doesNotCreateIndexForEntityComingFromDifferentMappingContext() { MongoMappingContext mappingContext = new MongoMappingContext(); MongoMappingContext personMappingContext = prepareMappingContext(Person.class); @@ -115,7 +119,7 @@ public void doesNotCreateIndexForEntityComingFromDifferentMappingContext() { } @Test // DATAMONGO-530 - public void isIndexCreatorForMappingContextHandedIntoConstructor() { + void isIndexCreatorForMappingContextHandedIntoConstructor() { MongoMappingContext mappingContext = new MongoMappingContext(); mappingContext.initialize(); @@ -126,7 +130,7 @@ public void isIndexCreatorForMappingContextHandedIntoConstructor() { } @Test // DATAMONGO-554 - public void triggersBackgroundIndexingIfConfigured() { + void triggersBackgroundIndexingIfConfigured() { MongoMappingContext mappingContext = prepareMappingContext(AnotherPerson.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); @@ -138,7 +142,7 @@ public void triggersBackgroundIndexingIfConfigured() { } @Test // DATAMONGO-544 - public void expireAfterSecondsIfConfigured() { + void expireAfterSecondsIfConfigured() { MongoMappingContext mappingContext = prepareMappingContext(Milk.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); @@ -148,7 +152,7 @@ public void expireAfterSecondsIfConfigured() { } @Test // DATAMONGO-899 - public void createsNotNestedGeoSpatialIndexCorrectly() { + void createsNotNestedGeoSpatialIndexCorrectly() { MongoMappingContext mappingContext = prepareMappingContext(Wrapper.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); @@ -163,7 +167,7 @@ public void createsNotNestedGeoSpatialIndexCorrectly() { } @Test // DATAMONGO-827 - public void autoGeneratedIndexNameShouldGenerateNoName() { + void autoGeneratedIndexNameShouldGenerateNoName() { MongoMappingContext mappingContext = prepareMappingContext(EntityWithGeneratedIndexName.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); @@ -173,7 +177,7 @@ public void autoGeneratedIndexNameShouldGenerateNoName() { } @Test // DATAMONGO-367 - public void indexCreationShouldNotCreateNewCollectionForNestedGeoSpatialIndexStructures() { + void indexCreationShouldNotCreateNewCollectionForNestedGeoSpatialIndexStructures() { MongoMappingContext mappingContext = prepareMappingContext(Wrapper.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); @@ -185,7 +189,7 @@ public void indexCreationShouldNotCreateNewCollectionForNestedGeoSpatialIndexStr } @Test // DATAMONGO-367 - public void indexCreationShouldNotCreateNewCollectionForNestedIndexStructures() { + void indexCreationShouldNotCreateNewCollectionForNestedIndexStructures() { MongoMappingContext mappingContext = prepareMappingContext(IndexedDocumentWrapper.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); @@ -196,26 +200,28 @@ public void indexCreationShouldNotCreateNewCollectionForNestedIndexStructures() assertThat(collectionNameCapturer.getValue()).isEqualTo("indexedDocumentWrapper"); } - @Test(expected = DataAccessException.class) // DATAMONGO-1125 - public void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() { + @Test // DATAMONGO-1125 + void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() { doThrow(new MongoException(6, "HostUnreachable")).when(collection).createIndex(any(org.bson.Document.class), any(IndexOptions.class)); MongoMappingContext mappingContext = prepareMappingContext(Person.class); - new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); + assertThatThrownBy(() -> new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate)) + .isInstanceOf(DataAccessException.class); } - @Test(expected = ClassCastException.class) // DATAMONGO-1125 - public void createIndexShouldNotConvertUnknownExceptionTypes() { + @Test // DATAMONGO-1125 + void createIndexShouldNotConvertUnknownExceptionTypes() { doThrow(new ClassCastException("o_O")).when(collection).createIndex(any(org.bson.Document.class), any(IndexOptions.class)); MongoMappingContext mappingContext = prepareMappingContext(Person.class); - new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); + assertThatThrownBy(() -> new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate)) + .isInstanceOf(ClassCastException.class); } private static MongoMappingContext prepareMappingContext(Class type) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 0c9f2e9a76..cd6de29f3e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -25,7 +25,7 @@ import java.util.Collections; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java index 0de564be78..10374088e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java @@ -24,12 +24,13 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoExceptionTranslator; @@ -48,22 +49,22 @@ * * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { - ReactiveIndexOperations indexOperations; + private ReactiveIndexOperations indexOperations; @Mock ReactiveMongoDatabaseFactory factory; @Mock MongoDatabase db; @Mock MongoCollection collection; - ArgumentCaptor keysCaptor; - ArgumentCaptor optionsCaptor; - ArgumentCaptor collectionCaptor; + private ArgumentCaptor keysCaptor; + private ArgumentCaptor optionsCaptor; + private ArgumentCaptor collectionCaptor; - @Before + @BeforeEach @SuppressWarnings("unchecked") - public void setUp() { + void setUp() { when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); when(factory.getMongoDatabase()).thenReturn(db); @@ -79,7 +80,7 @@ public void setUp() { } @Test // DATAMONGO-1928 - public void buildsIndexDefinitionUsingFieldName() { + void buildsIndexDefinitionUsingFieldName() { MongoMappingContext mappingContext = prepareMappingContext(Person.class); @@ -96,7 +97,7 @@ public void buildsIndexDefinitionUsingFieldName() { } @Test // DATAMONGO-1928 - public void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() { + void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() { when(collection.createIndex(any(org.bson.Document.class), any(IndexOptions.class))) .thenReturn(Mono.error(new MongoException(6, "HostUnreachable"))); @@ -109,7 +110,7 @@ public void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrit } @Test // DATAMONGO-1928 - public void createIndexShouldNotConvertUnknownExceptionTypes() { + void createIndexShouldNotConvertUnknownExceptionTypes() { when(collection.createIndex(any(org.bson.Document.class), any(IndexOptions.class))) .thenReturn(Mono.error(new ClassCastException("o_O"))); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java index 07100b9405..bdc22b3bd8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java @@ -26,10 +26,11 @@ import java.util.LinkedHashMap; import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AliasFor; import org.springframework.data.mapping.MappingException; @@ -43,14 +44,14 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class BasicMongoPersistentEntityUnitTests { @Mock ApplicationContext context; @Mock MongoPersistentProperty propertyMock; @Test - public void subclassInheritsAtDocumentAnnotation() { + void subclassInheritsAtDocumentAnnotation() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( ClassTypeInformation.from(Person.class)); @@ -58,7 +59,7 @@ public void subclassInheritsAtDocumentAnnotation() { } @Test - public void evaluatesSpELExpression() { + void evaluatesSpELExpression() { MongoPersistentEntity entity = new BasicMongoPersistentEntity( ClassTypeInformation.from(Company.class)); @@ -66,7 +67,7 @@ public void evaluatesSpELExpression() { } @Test // DATAMONGO-65, DATAMONGO-1108 - public void collectionAllowsReferencingSpringBean() { + void collectionAllowsReferencingSpringBean() { CollectionProvider provider = new CollectionProvider(); provider.collectionName = "reference"; @@ -84,7 +85,7 @@ public void collectionAllowsReferencingSpringBean() { } @Test // DATAMONGO-937 - public void shouldDetectLanguageCorrectly() { + void shouldDetectLanguageCorrectly() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( ClassTypeInformation.from(DocumentWithLanguage.class)); @@ -93,7 +94,7 @@ public void shouldDetectLanguageCorrectly() { } @Test // DATAMONGO-1053 - public void verifyShouldThrowExceptionForInvalidTypeOfExplicitLanguageProperty() { + void verifyShouldThrowExceptionForInvalidTypeOfExplicitLanguageProperty() { doReturn(true).when(propertyMock).isExplicitLanguageProperty(); doReturn(Number.class).when(propertyMock).getActualType(); @@ -106,7 +107,7 @@ public void verifyShouldThrowExceptionForInvalidTypeOfExplicitLanguageProperty() } @Test // DATAMONGO-1053 - public void verifyShouldPassForStringAsExplicitLanguageProperty() { + void verifyShouldPassForStringAsExplicitLanguageProperty() { doReturn(true).when(propertyMock).isExplicitLanguageProperty(); doReturn(String.class).when(propertyMock).getActualType(); @@ -122,7 +123,7 @@ public void verifyShouldPassForStringAsExplicitLanguageProperty() { } @Test // DATAMONGO-1053 - public void verifyShouldIgnoreNonExplicitLanguageProperty() { + void verifyShouldIgnoreNonExplicitLanguageProperty() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( ClassTypeInformation.from(AnyDocument.class)); @@ -136,7 +137,7 @@ public void verifyShouldIgnoreNonExplicitLanguageProperty() { } @Test // DATAMONGO-1157 - public void verifyShouldThrowErrorForLazyDBRefOnFinalClass() { + void verifyShouldThrowErrorForLazyDBRefOnFinalClass() { org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( org.springframework.data.mongodb.core.mapping.DBRef.class); @@ -154,7 +155,7 @@ public void verifyShouldThrowErrorForLazyDBRefOnFinalClass() { } @Test // DATAMONGO-1157 - public void verifyShouldThrowErrorForLazyDBRefArray() { + void verifyShouldThrowErrorForLazyDBRefArray() { org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( org.springframework.data.mongodb.core.mapping.DBRef.class); @@ -172,7 +173,7 @@ public void verifyShouldThrowErrorForLazyDBRefArray() { } @Test // DATAMONGO-1157 - public void verifyShouldPassForLazyDBRefOnNonArrayNonFinalClass() { + void verifyShouldPassForLazyDBRefOnNonArrayNonFinalClass() { org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( org.springframework.data.mongodb.core.mapping.DBRef.class); @@ -191,7 +192,7 @@ public void verifyShouldPassForLazyDBRefOnNonArrayNonFinalClass() { } @Test // DATAMONGO-1157 - public void verifyShouldPassForNonLazyDBRefOnFinalClass() { + void verifyShouldPassForNonLazyDBRefOnFinalClass() { org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( org.springframework.data.mongodb.core.mapping.DBRef.class); @@ -209,7 +210,7 @@ public void verifyShouldPassForNonLazyDBRefOnFinalClass() { } @Test // DATAMONGO-1291 - public void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation() { + void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( ClassTypeInformation.from(DocumentWithCustomAnnotation.class)); @@ -218,7 +219,7 @@ public void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation( } @Test // DATAMONGO-1373 - public void metaInformationShouldBeReadCorrectlyFromComposedDocumentAnnotation() { + void metaInformationShouldBeReadCorrectlyFromComposedDocumentAnnotation() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( ClassTypeInformation.from(DocumentWithComposedAnnotation.class)); @@ -227,7 +228,7 @@ public void metaInformationShouldBeReadCorrectlyFromComposedDocumentAnnotation() } @Test // DATAMONGO-1874 - public void usesEvaluationContextExtensionInDynamicDocumentName() { + void usesEvaluationContextExtensionInDynamicDocumentName() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(MappedWithExtension.class)); @@ -238,7 +239,7 @@ public void usesEvaluationContextExtensionInDynamicDocumentName() { } @Test // DATAMONGO-1854 - public void readsSimpleCollation() { + void readsSimpleCollation() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(WithSimpleCollation.class)); @@ -247,7 +248,7 @@ public void readsSimpleCollation() { } @Test // DATAMONGO-1854 - public void readsDocumentCollation() { + void readsDocumentCollation() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(WithDocumentCollation.class)); @@ -256,28 +257,28 @@ public void readsDocumentCollation() { } @Test // DATAMONGO-2341 - public void detectsShardedEntityCorrectly() { + void detectsShardedEntityCorrectly() { assertThat(entityOf(WithDefaultShardKey.class).isSharded()).isTrue(); assertThat(entityOf(Contact.class).isSharded()).isFalse(); } @Test // DATAMONGO-2341 - public void readsDefaultShardKey() { + void readsDefaultShardKey() { assertThat(entityOf(WithDefaultShardKey.class).getShardKey().getDocument()) .isEqualTo(new org.bson.Document("_id", 1)); } @Test // DATAMONGO-2341 - public void readsSingleShardKey() { + void readsSingleShardKey() { assertThat(entityOf(WithSingleShardKey.class).getShardKey().getDocument()) .isEqualTo(new org.bson.Document("country", 1)); } @Test // DATAMONGO-2341 - public void readsMultiShardKey() { + void readsMultiShardKey() { assertThat(entityOf(WithMultiShardKey.class).getShardKey().getDocument()) .isEqualTo(new org.bson.Document("country", 1).append("userid", 1)); @@ -309,13 +310,13 @@ public String getCollectionName() { @Document(language = "spanish") static class DocumentWithLanguage {} - static class AnyDocument {} + private static class AnyDocument {} @CustomDocumentAnnotation - static class DocumentWithCustomAnnotation {} + private static class DocumentWithCustomAnnotation {} @ComposedDocumentAnnotation - static class DocumentWithComposedAnnotation {} + private static class DocumentWithComposedAnnotation {} @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) @@ -346,17 +347,20 @@ class WithSimpleCollation {} class WithDocumentCollation {} @Sharded + private class WithDefaultShardKey {} @Sharded("country") + private class WithSingleShardKey {} @Sharded({ "country", "userid" }) + private class WithMultiShardKey {} static class SampleExtension implements EvaluationContextExtension { - /* + /* * (non-Javadoc) * @see org.springframework.data.spel.spi.EvaluationContextExtension#getExtensionId() */ @@ -365,7 +369,7 @@ public String getExtensionId() { return "sampleExtension"; } - /* + /* * (non-Javadoc) * @see org.springframework.data.spel.spi.EvaluationContextExtension#getProperties() */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 6baaa7899a..8585a5c7f0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -28,8 +28,8 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.core.annotation.AliasFor; import org.springframework.data.annotation.Id; @@ -53,7 +53,7 @@ public class BasicMongoPersistentPropertyUnitTests { MongoPersistentEntity entity; - @Before + @BeforeEach public void setup() { entity = new BasicMongoPersistentEntity<>(ClassTypeInformation.from(Person.class)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java index 8fde5b50c7..765c01367b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java @@ -20,11 +20,11 @@ import java.util.Collections; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -35,16 +35,16 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class GenericMappingTests { +@ExtendWith(MockitoExtension.class) +class GenericMappingTests { - MongoMappingContext context; - MongoConverter converter; + private MongoMappingContext context; + private MongoConverter converter; @Mock DbRefResolver resolver; - @Before - public void setUp() throws Exception { + @BeforeEach + void setUp() throws Exception { context = new MongoMappingContext(); context.setInitialEntitySet(Collections.singleton(StringWrapper.class)); @@ -54,7 +54,7 @@ public void setUp() throws Exception { } @Test - public void writesGenericTypeCorrectly() { + void writesGenericTypeCorrectly() { StringWrapper wrapper = new StringWrapper(); wrapper.container = new Container(); @@ -73,7 +73,7 @@ public void writesGenericTypeCorrectly() { } @Test - public void readsGenericTypeCorrectly() { + void readsGenericTypeCorrectly() { Document content = new Document("content", "Foo!"); Document container = new Document("container", content); @@ -83,7 +83,7 @@ public void readsGenericTypeCorrectly() { assertThat(result.container.content).isEqualTo("Foo!"); } - static class StringWrapper extends Wrapper { + private static class StringWrapper extends Wrapper { } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java index 9bf2ac676d..d922edd951 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java @@ -22,10 +22,10 @@ import java.util.Locale; import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.context.ApplicationContext; import org.springframework.data.annotation.Id; @@ -43,13 +43,13 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MongoMappingContextUnitTests { @Mock ApplicationContext applicationContext; @Test - public void addsSelfReferencingPersistentEntityCorrectly() throws Exception { + void addsSelfReferencingPersistentEntityCorrectly() throws Exception { MongoMappingContext context = new MongoMappingContext(); @@ -58,21 +58,21 @@ public void addsSelfReferencingPersistentEntityCorrectly() throws Exception { } @Test - public void doesNotReturnPersistentEntityForMongoSimpleType() { + void doesNotReturnPersistentEntityForMongoSimpleType() { MongoMappingContext context = new MongoMappingContext(); assertThat(context.getPersistentEntity(DBRef.class)).isNull(); } @Test // DATAMONGO-638 - public void doesNotCreatePersistentEntityForAbstractMap() { + void doesNotCreatePersistentEntityForAbstractMap() { MongoMappingContext context = new MongoMappingContext(); assertThat(context.getPersistentEntity(AbstractMap.class)).isNull(); } @Test // DATAMONGO-607 - public void populatesPersistentPropertyWithCustomFieldNamingStrategy() { + void populatesPersistentPropertyWithCustomFieldNamingStrategy() { MongoMappingContext context = new MongoMappingContext(); context.setApplicationContext(applicationContext); @@ -88,7 +88,7 @@ public String getFieldName(PersistentProperty property) { } @Test // DATAMONGO-607 - public void rejectsClassWithAmbiguousFieldMappings() { + void rejectsClassWithAmbiguousFieldMappings() { MongoMappingContext context = new MongoMappingContext(); context.setApplicationContext(applicationContext); @@ -99,7 +99,7 @@ public void rejectsClassWithAmbiguousFieldMappings() { } @Test // DATAMONGO-694 - public void doesNotConsiderOverrridenAccessorANewField() { + void doesNotConsiderOverrridenAccessorANewField() { MongoMappingContext context = new MongoMappingContext(); context.setApplicationContext(applicationContext); @@ -107,7 +107,7 @@ public void doesNotConsiderOverrridenAccessorANewField() { } @Test // DATAMONGO-688 - public void mappingContextShouldAcceptClassWithImplicitIdProperty() { + void mappingContextShouldAcceptClassWithImplicitIdProperty() { MongoMappingContext context = new MongoMappingContext(); BasicMongoPersistentEntity pe = context.getRequiredPersistentEntity(ClassWithImplicitId.class); @@ -117,7 +117,7 @@ public void mappingContextShouldAcceptClassWithImplicitIdProperty() { } @Test // DATAMONGO-688 - public void mappingContextShouldAcceptClassWithExplicitIdProperty() { + void mappingContextShouldAcceptClassWithExplicitIdProperty() { MongoMappingContext context = new MongoMappingContext(); BasicMongoPersistentEntity pe = context.getRequiredPersistentEntity(ClassWithExplicitId.class); @@ -127,29 +127,31 @@ public void mappingContextShouldAcceptClassWithExplicitIdProperty() { } @Test // DATAMONGO-688 - public void mappingContextShouldAcceptClassWithExplicitAndImplicitIdPropertyByGivingPrecedenceToExplicitIdProperty() { + void mappingContextShouldAcceptClassWithExplicitAndImplicitIdPropertyByGivingPrecedenceToExplicitIdProperty() { MongoMappingContext context = new MongoMappingContext(); BasicMongoPersistentEntity pe = context.getRequiredPersistentEntity(ClassWithExplicitIdAndImplicitId.class); assertThat(pe).isNotNull(); } - @Test(expected = MappingException.class) // DATAMONGO-688 - public void rejectsClassWithAmbiguousExplicitIdPropertyFieldMappings() { + @Test // DATAMONGO-688 + void rejectsClassWithAmbiguousExplicitIdPropertyFieldMappings() { MongoMappingContext context = new MongoMappingContext(); - context.getPersistentEntity(ClassWithMultipleExplicitIds.class); + assertThatThrownBy(() -> context.getPersistentEntity(ClassWithMultipleExplicitIds.class)) + .isInstanceOf(MappingException.class); } - @Test(expected = MappingException.class) // DATAMONGO-688 - public void rejectsClassWithAmbiguousImplicitIdPropertyFieldMappings() { + @Test // DATAMONGO-688 + void rejectsClassWithAmbiguousImplicitIdPropertyFieldMappings() { MongoMappingContext context = new MongoMappingContext(); - context.getPersistentEntity(ClassWithMultipleImplicitIds.class); + assertThatThrownBy(() -> context.getPersistentEntity(ClassWithMultipleImplicitIds.class)) + .isInstanceOf(MappingException.class); } @Test // DATAMONGO-976 - public void shouldRejectClassWithInvalidTextScoreProperty() { + void shouldRejectClassWithInvalidTextScoreProperty() { MongoMappingContext context = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java index b0a013ae5f..9ebeb68ceb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoPersistentPropertyComparatorUnitTests.java @@ -7,10 +7,10 @@ import java.util.Collections; import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity.MongoPersistentPropertyComparator; @@ -19,8 +19,8 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class MongoPersistentPropertyComparatorUnitTests { +@ExtendWith(MockitoExtension.class) +class MongoPersistentPropertyComparatorUnitTests { @Mock MongoPersistentProperty firstName; @@ -29,7 +29,7 @@ public class MongoPersistentPropertyComparatorUnitTests { @Mock MongoPersistentProperty ssn; @Test - public void ordersPropertiesCorrectly() { + void ordersPropertiesCorrectly() { when(ssn.getFieldOrder()).thenReturn(10); when(firstName.getFieldOrder()).thenReturn(20); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java index 7a5a59815b..83b268d7f3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java index 1cc0913aa0..9f31067bc3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallbackUnitTests.java @@ -27,11 +27,10 @@ import java.util.Arrays; import java.util.Date; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalAnswers; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.Ordered; import org.springframework.data.annotation.CreatedDate; @@ -46,33 +45,30 @@ * * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class AuditingEntityCallbackUnitTests { - IsNewAwareAuditingHandler handler; - AuditingEntityCallback callback; + private IsNewAwareAuditingHandler handler; + private AuditingEntityCallback callback; - @Before - public void setUp() { + @BeforeEach + void setUp() { MongoMappingContext mappingContext = new MongoMappingContext(); mappingContext.getPersistentEntity(Sample.class); handler = spy(new IsNewAwareAuditingHandler(new PersistentEntities(Arrays.asList(mappingContext)))); - doAnswer(AdditionalAnswers.returnsArgAt(0)).when(handler).markCreated(any()); - doAnswer(AdditionalAnswers.returnsArgAt(0)).when(handler).markModified(any()); - callback = new AuditingEntityCallback(() -> handler); } @Test // DATAMONGO-2261 - public void rejectsNullAuditingHandler() { + void rejectsNullAuditingHandler() { assertThatIllegalArgumentException().isThrownBy(() -> new AuditingEntityCallback(null)); } @Test // DATAMONGO-2261 - public void triggersCreationMarkForObjectWithEmptyId() { + void triggersCreationMarkForObjectWithEmptyId() { Sample sample = new Sample(); callback.onBeforeConvert(sample, "foo"); @@ -82,7 +78,7 @@ public void triggersCreationMarkForObjectWithEmptyId() { } @Test // DATAMONGO-2261 - public void triggersModificationMarkForObjectWithSetId() { + void triggersModificationMarkForObjectWithSetId() { Sample sample = new Sample(); sample.id = "id"; @@ -93,14 +89,14 @@ public void triggersModificationMarkForObjectWithSetId() { } @Test // DATAMONGO-2261 - public void hasExplicitOrder() { + void hasExplicitOrder() { assertThat(callback).isInstanceOf(Ordered.class); assertThat(callback.getOrder()).isEqualTo(100); } @Test // DATAMONGO-2261 - public void propagatesChangedInstanceToEvent() { + void propagatesChangedInstanceToEvent() { ImmutableSample sample = new ImmutableSample(); @@ -125,7 +121,7 @@ static class Sample { @Wither @AllArgsConstructor @NoArgsConstructor(force = true) - static class ImmutableSample { + private static class ImmutableSample { @Id String id; @CreatedDate Date created; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java index 34cb376f48..4697b1fa67 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListenerUnitTests.java @@ -27,11 +27,10 @@ import java.util.Arrays; import java.util.Date; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalAnswers; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.Ordered; import org.springframework.data.annotation.CreatedDate; @@ -47,33 +46,29 @@ * @author Oliver Gierke * @author Thomas Darimont */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class AuditingEventListenerUnitTests { - IsNewAwareAuditingHandler handler; - AuditingEventListener listener; + private IsNewAwareAuditingHandler handler; + private AuditingEventListener listener; - @Before - public void setUp() { + @BeforeEach + void setUp() { MongoMappingContext mappingContext = new MongoMappingContext(); mappingContext.getPersistentEntity(Sample.class); handler = spy(new IsNewAwareAuditingHandler(new PersistentEntities(Arrays.asList(mappingContext)))); - - doAnswer(AdditionalAnswers.returnsArgAt(0)).when(handler).markCreated(any()); - doAnswer(AdditionalAnswers.returnsArgAt(0)).when(handler).markModified(any()); - listener = new AuditingEventListener(() -> handler); } @Test // DATAMONGO-577 - public void rejectsNullAuditingHandler() { + void rejectsNullAuditingHandler() { assertThatIllegalArgumentException().isThrownBy(() -> new AuditingEventListener(null)); } @Test // DATAMONGO-577 - public void triggersCreationMarkForObjectWithEmptyId() { + void triggersCreationMarkForObjectWithEmptyId() { Sample sample = new Sample(); listener.onApplicationEvent(new BeforeConvertEvent(sample, "collection-1")); @@ -83,7 +78,7 @@ public void triggersCreationMarkForObjectWithEmptyId() { } @Test // DATAMONGO-577 - public void triggersModificationMarkForObjectWithSetId() { + void triggersModificationMarkForObjectWithSetId() { Sample sample = new Sample(); sample.id = "id"; @@ -94,14 +89,14 @@ public void triggersModificationMarkForObjectWithSetId() { } @Test - public void hasExplicitOrder() { + void hasExplicitOrder() { assertThat(listener).isInstanceOf(Ordered.class); assertThat(listener.getOrder()).isEqualTo(100); } @Test // DATAMONGO-1992 - public void propagatesChangedInstanceToEvent() { + void propagatesChangedInstanceToEvent() { ImmutableSample sample = new ImmutableSample(); BeforeConvertEvent event = new BeforeConvertEvent<>(sample, "collection"); @@ -127,7 +122,7 @@ static class Sample { @Wither @AllArgsConstructor @NoArgsConstructor(force = true) - static class ImmutableSample { + private static class ImmutableSample { @Id String id; @CreatedDate Date created; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java index 6cd602bba7..b721a40ce7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListenerTests.java @@ -22,9 +22,9 @@ import ch.qos.logback.core.read.ListAppender; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; /** @@ -39,7 +39,7 @@ public class LoggingEventListenerTests { ch.qos.logback.classic.Logger logger; LoggingEventListener listener; - @Before + @BeforeEach public void setUp() { appender = new ListAppender(); @@ -56,7 +56,7 @@ public void setUp() { listener = new LoggingEventListener(); } - @After + @AfterEach public void tearDown() { // cleanup diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java index fafe8cd90a..a0a7e963d1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListenerTests.java @@ -19,16 +19,13 @@ import javax.validation.ConstraintViolationException; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; /** * Integration test for {@link ValidatingMongoEventListener}. @@ -37,16 +34,14 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith(SpringExtension.class) @ContextConfiguration -public class ValidatingMongoEventListenerTests { - - public static @ClassRule MongoVersionRule version = MongoVersionRule.atLeast(new Version(2, 6)); +class ValidatingMongoEventListenerTests { @Autowired MongoTemplate mongoTemplate; @Test // DATAMONGO-36 - public void shouldThrowConstraintViolationException() { + void shouldThrowConstraintViolationException() { User user = new User("john", 17); @@ -57,7 +52,7 @@ public void shouldThrowConstraintViolationException() { } @Test - public void shouldNotThrowAnyExceptions() { + void shouldNotThrowAnyExceptions() { mongoTemplate.save(new User("john smith", 18)); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java index 3b00892638..b523e27b84 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCountsUnitTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link MapReduceCounts}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java index e0b0d184e3..17161529d0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptionsTests.java @@ -17,7 +17,7 @@ import static org.springframework.data.mongodb.test.util.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * @author Mark Pollack diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java index 731f6cff8e..17c2b48f1b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResultsUnitTests.java @@ -20,7 +20,7 @@ import java.util.Collections; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link MapReduceResults}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java index 689f930392..1bd4d213e8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTaskUnitTests.java @@ -22,11 +22,11 @@ import org.bson.BsonDocument; import org.bson.BsonString; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -43,18 +43,18 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class ChangeStreamTaskUnitTests { +@ExtendWith(MockitoExtension.class) +class ChangeStreamTaskUnitTests { ChangeStreamTask task; @Mock MongoTemplate template; @Mock MongoDatabase mongoDatabase; @Mock MongoCollection mongoCollection; @Mock ChangeStreamIterable changeStreamIterable; - MongoConverter converter; + private MongoConverter converter; - @Before - public void setUp() { + @BeforeEach + void setUp() { MongoMappingContext mappingContext = new MongoMappingContext(); converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); @@ -66,15 +66,14 @@ public void setUp() { when(mongoCollection.watch(eq(Document.class))).thenReturn(changeStreamIterable); - when(changeStreamIterable.startAfter(any())).thenReturn(changeStreamIterable); - when(changeStreamIterable.resumeAfter(any())).thenReturn(changeStreamIterable); when(changeStreamIterable.fullDocument(any())).thenReturn(changeStreamIterable); } @Test // DATAMONGO-2258 - public void shouldNotBreakLovelaceBehavior() { + void shouldNotBreakLovelaceBehavior() { BsonDocument resumeToken = new BsonDocument("token", new BsonString(UUID.randomUUID().toString())); + when(changeStreamIterable.resumeAfter(any())).thenReturn(changeStreamIterable); ChangeStreamRequest request = ChangeStreamRequest.builder() // .collection("start-wars") // @@ -88,7 +87,9 @@ public void shouldNotBreakLovelaceBehavior() { } @Test // DATAMONGO-2258 - public void shouldApplyResumeAfterToChangeStream() { + void shouldApplyResumeAfterToChangeStream() { + + when(changeStreamIterable.resumeAfter(any())).thenReturn(changeStreamIterable); BsonDocument resumeToken = new BsonDocument("token", new BsonString(UUID.randomUUID().toString())); @@ -104,7 +105,9 @@ public void shouldApplyResumeAfterToChangeStream() { } @Test // DATAMONGO-2258 - public void shouldApplyStartAfterToChangeStream() { + void shouldApplyStartAfterToChangeStream() { + + when(changeStreamIterable.startAfter(any())).thenReturn(changeStreamIterable); BsonDocument resumeToken = new BsonDocument("token", new BsonString(UUID.randomUUID().toString())); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index e0f255352b..275f258959 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -59,6 +59,7 @@ import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; +import org.junitpioneer.jupiter.RepeatFailedTest; /** * Integration test for subscribing to a {@link com.mongodb.operation.ChangeStreamBatchCursor} inside the @@ -69,26 +70,26 @@ */ @ExtendWith({ MongoTemplateExtension.class }) @EnableIfReplicaSetAvailable -public class ChangeStreamTests { +class ChangeStreamTests { - static ThreadPoolExecutor executor; + private static ThreadPoolExecutor executor; @Template(initialEntitySet = User.class, replicaSet = true) // - static MongoTestTemplate template; + private static MongoTestTemplate template; - MessageListenerContainer container; + private MessageListenerContainer container; - User jellyBelly; - User huffyFluffy; - User sugarSplashy; + private User jellyBelly; + private User huffyFluffy; + private User sugarSplashy; @BeforeAll - public static void beforeClass() { + static void beforeClass() { executor = new ThreadPoolExecutor(2, 2, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); } @BeforeEach - public void setUp() { + void setUp() { template.dropCollection(User.class); @@ -112,17 +113,17 @@ public void setUp() { } @AfterEach - public void tearDown() { + void tearDown() { container.stop(); } @AfterAll - public static void afterClass() { + static void afterClass() { executor.shutdown(); } @Test // DATAMONGO-1803 - public void readsPlainDocumentMessageCorrectly() throws InterruptedException { + void readsPlainDocumentMessageCorrectly() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, @@ -145,7 +146,7 @@ public void readsPlainDocumentMessageCorrectly() throws InterruptedException { } @Test // DATAMONGO-1803 - public void useSimpleAggregationToFilterMessages() throws InterruptedException { + void useSimpleAggregationToFilterMessages() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // @@ -171,7 +172,7 @@ public void useSimpleAggregationToFilterMessages() throws InterruptedException { @Test // DATAMONGO-1803 @MongoVersion(asOf = "4.0") - public void useAggregationToFilterMessages() throws InterruptedException { + void useAggregationToFilterMessages() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // @@ -197,7 +198,8 @@ public void useAggregationToFilterMessages() throws InterruptedException { } @Test // DATAMONGO-1803 - public void mapsTypedAggregationToFilterMessages() throws InterruptedException { + @RepeatFailedTest(3) + void mapsTypedAggregationToFilterMessages() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder() // @@ -224,7 +226,7 @@ public void mapsTypedAggregationToFilterMessages() throws InterruptedException { } @Test // DATAMONGO-1803 - public void mapsReservedWordsCorrectly() throws InterruptedException { + void mapsReservedWordsCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder() // @@ -256,7 +258,7 @@ public void mapsReservedWordsCorrectly() throws InterruptedException { } @Test // DATAMONGO-1803 - public void plainAggregationPipelineToFilterMessages() throws InterruptedException { + void plainAggregationPipelineToFilterMessages() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder() // @@ -282,7 +284,7 @@ public void plainAggregationPipelineToFilterMessages() throws InterruptedExcepti } @Test // DATAMONGO-1803 - public void resumesCorrectly() throws InterruptedException { + void resumesCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); Subscription subscription1 = container.register( @@ -316,7 +318,7 @@ public void resumesCorrectly() throws InterruptedException { } @Test // DATAMONGO-1803 - public void readsAndConvertsMessageBodyCorrectly() throws InterruptedException { + void readsAndConvertsMessageBodyCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, @@ -338,7 +340,7 @@ public void readsAndConvertsMessageBodyCorrectly() throws InterruptedException { } @Test // DATAMONGO-1803 - public void readsAndConvertsUpdateMessageBodyCorrectly() throws InterruptedException { + void readsAndConvertsUpdateMessageBodyCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, @@ -358,7 +360,7 @@ public void readsAndConvertsUpdateMessageBodyCorrectly() throws InterruptedExcep } @Test // DATAMONGO-1803 - public void readsOnlyDiffForUpdateWhenNotMappedToDomainType() throws InterruptedException { + void readsOnlyDiffForUpdateWhenNotMappedToDomainType() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, @@ -379,7 +381,7 @@ public void readsOnlyDiffForUpdateWhenNotMappedToDomainType() throws Interrupted } @Test // DATAMONGO-1803 - public void readsOnlyDiffForUpdateWhenOptionsDeclareDefaultExplicitly() throws InterruptedException { + void readsOnlyDiffForUpdateWhenOptionsDeclareDefaultExplicitly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder() // @@ -403,7 +405,7 @@ public void readsOnlyDiffForUpdateWhenOptionsDeclareDefaultExplicitly() throws I @Test // DATAMONGO-1803 @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") - public void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecified() throws InterruptedException { + void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecified() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder() // @@ -429,7 +431,7 @@ public void readsFullDocumentForUpdateWhenNotMappedToDomainTypeButLookupSpecifie @Test // DATAMONGO-2012, DATAMONGO-2113 @MongoVersion(asOf = "4.0") - public void resumeAtTimestampCorrectly() throws InterruptedException { + void resumeAtTimestampCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); Subscription subscription1 = container.register( @@ -473,7 +475,7 @@ public void resumeAtTimestampCorrectly() throws InterruptedException { } @Test // DATAMONGO-1996 - public void filterOnNestedElementWorksCorrectly() throws InterruptedException { + void filterOnNestedElementWorksCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // @@ -504,7 +506,7 @@ public void filterOnNestedElementWorksCorrectly() throws InterruptedException { } @Test // DATAMONGO-1996 - public void filterOnUpdateDescriptionElement() throws InterruptedException { + void filterOnUpdateDescriptionElement() throws InterruptedException { template.save(jellyBelly); template.save(sugarSplashy); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java index c3f955a670..02fc92be5a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/CursorReadingTaskUnitTests.java @@ -24,17 +24,19 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.messaging.Task.State; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; +import org.springframework.data.mongodb.core.messaging.Task.State; import org.springframework.util.ErrorHandler; import com.mongodb.ServerAddress; @@ -47,7 +49,8 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.Silent.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class CursorReadingTaskUnitTests { @Mock MongoDatabase db; @@ -60,7 +63,7 @@ public class CursorReadingTaskUnitTests { ValueCapturingTaskStub task; - @Before + @BeforeEach public void setUp() { when(request.getRequestOptions()).thenReturn(options); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java index 23317f1b68..dff08d2516 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerUnitTests.java @@ -22,11 +22,12 @@ import java.time.Duration; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.util.ErrorHandler; @@ -36,46 +37,46 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class DefaultMessageListenerContainerUnitTests { +@ExtendWith(MockitoExtension.class) +class DefaultMessageListenerContainerUnitTests { @Mock MongoTemplate template; @Mock ErrorHandler errorHandler; - DefaultMessageListenerContainer container; + private DefaultMessageListenerContainer container; - @Before - public void setUp() { + @BeforeEach + void setUp() { container = new DefaultMessageListenerContainer(template); } @Test // DATAMONGO-1803 - public void throwsErrorOnNullTemplate() { + void throwsErrorOnNullTemplate() { assertThatIllegalArgumentException().isThrownBy(() -> new DefaultMessageListenerContainer(null)); } @Test // DATAMONGO-1803 - public void startStopContainer() throws Throwable { + void startStopContainer() throws Throwable { runOnce(new MultithreadedStartStopContainer(container)); } @Test // DATAMONGO-1803 - public void subscribeToContainerBeforeStartup() throws Throwable { + void subscribeToContainerBeforeStartup() throws Throwable { runOnce(new MultithreadedSubscribeBeforeStartup(container)); } @Test // DATAMONGO-1803 - public void subscribeToContainerAfterStartup() throws Throwable { + void subscribeToContainerAfterStartup() throws Throwable { runOnce(new MultithreadedSubscribeAfterStartup(container)); } @Test // DATAMONGO-1803 - public void stopSubscriptionWhileRunning() throws Throwable { + void stopSubscriptionWhileRunning() throws Throwable { runOnce(new StopSubscriptionWhileRunning(container)); } @Test // DATAMONGO-1803 - public void removeSubscriptionWhileRunning() throws Throwable { + void removeSubscriptionWhileRunning() throws Throwable { runOnce(new RemoveSubscriptionWhileRunning(container)); } @@ -84,7 +85,7 @@ private static class RemoveSubscriptionWhileRunning extends MultithreadedTestCas DefaultMessageListenerContainer container; Subscription subscription; - public RemoveSubscriptionWhileRunning(DefaultMessageListenerContainer container) { + RemoveSubscriptionWhileRunning(DefaultMessageListenerContainer container) { this.container = container; subscription = container.register(new MockSubscriptionRequest(), new MockTask()); } @@ -114,7 +115,7 @@ private static class StopSubscriptionWhileRunning extends MultithreadedTestCase DefaultMessageListenerContainer container; Subscription subscription; - public StopSubscriptionWhileRunning(DefaultMessageListenerContainer container) { + StopSubscriptionWhileRunning(DefaultMessageListenerContainer container) { this.container = container; subscription = container.register(new MockSubscriptionRequest(), new MockTask()); } @@ -144,7 +145,7 @@ private static class MultithreadedSubscribeAfterStartup extends MultithreadedTes DefaultMessageListenerContainer container; - public MultithreadedSubscribeAfterStartup(DefaultMessageListenerContainer container) { + MultithreadedSubscribeAfterStartup(DefaultMessageListenerContainer container) { this.container = container; } @@ -174,7 +175,7 @@ private static class MultithreadedSubscribeBeforeStartup extends MultithreadedTe DefaultMessageListenerContainer container; - public MultithreadedSubscribeBeforeStartup(DefaultMessageListenerContainer container) { + MultithreadedSubscribeBeforeStartup(DefaultMessageListenerContainer container) { this.container = container; } @@ -207,7 +208,7 @@ private static class MultithreadedStartStopContainer extends MultithreadedTestCa DefaultMessageListenerContainer container; - public MultithreadedStartStopContainer(DefaultMessageListenerContainer container) { + MultithreadedStartStopContainer(DefaultMessageListenerContainer container) { this.container = container; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java index acde3583c7..4849a6685c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequestUnitTests.java @@ -19,7 +19,8 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; + import org.springframework.data.mongodb.core.messaging.DefaultMessageListenerContainerTests.Person; import org.springframework.data.mongodb.core.query.Query; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java index 25b2bce6c6..40be300f83 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TaskFactoryUnitTests.java @@ -18,12 +18,13 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions; @@ -35,30 +36,30 @@ * * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class TaskFactoryUnitTests { +@ExtendWith(MockitoExtension.class) +class TaskFactoryUnitTests { @Mock MongoConverter converter; @Mock MongoTemplate template; @Mock MessageListener messageListener; @Mock ErrorHandler errorHandler; - TaskFactory factory; - - @Before - public void setUp() { + private TaskFactory factory; - when(template.getConverter()).thenReturn(converter); + @BeforeEach + void setUp() { factory = new TaskFactory(template); } @Test // DATAMONGO-1803 - public void requestMustNotBeNull() { + void requestMustNotBeNull() { assertThatIllegalArgumentException().isThrownBy(() -> factory.forRequest(null, Object.class, errorHandler)); } @Test // DATAMONGO-1803 - public void createsChangeStreamRequestCorrectly() { + void createsChangeStreamRequestCorrectly() { + + when(template.getConverter()).thenReturn(converter); ChangeStreamRequestOptions options = Mockito.mock(ChangeStreamRequestOptions.class); Task task = factory.forRequest(new ChangeStreamRequest(messageListener, options), Object.class, errorHandler); @@ -67,7 +68,9 @@ public void createsChangeStreamRequestCorrectly() { } @Test // DATAMONGO-1803 - public void createsTailableRequestCorrectly() { + void createsTailableRequestCorrectly() { + + when(template.getConverter()).thenReturn(converter); RequestOptions options = Mockito.mock(RequestOptions.class); when(options.getCollectionName()).thenReturn("collection-1"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java index c14cfed676..b4961e3de1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java @@ -22,7 +22,7 @@ import nl.jqno.equalsverifier.Warning; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java index 1a73dea770..ee312f7846 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link DocumentField}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java index c87d7afedd..89a05d226c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/IndexUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java index a4e9cf7465..2c5d1f8cb5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/MetricConversionUnitTests.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.*; import static org.assertj.core.data.Offset.offset; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.geo.Distance; import org.springframework.data.geo.Metrics; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java index 1285a480cc..545d2d2ad0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/NearQueryUnitTests.java @@ -20,7 +20,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java index 0a3354c7ec..0ff6862cfa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/SortTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java index d30e7b97a1..ab2b4d9e4e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.DocumentTestUtils; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java index e40780cda1..791f9a4e5f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryUnitTests.java @@ -17,7 +17,7 @@ import static org.springframework.data.mongodb.test.util.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java index 426ef98537..a5c72274ba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcherUnitTests.java @@ -17,8 +17,9 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.domain.ExampleMatcher.NullHandler; import org.springframework.data.domain.ExampleMatcher.StringMatcher; @@ -30,7 +31,7 @@ public class UntypedExampleMatcherUnitTests { ExampleMatcher matcher; - @Before + @BeforeEach public void setUp() { matcher = UntypedExampleMatcher.matching(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java index aa8e857ae5..dd65e22e87 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/UpdateTests.java @@ -23,7 +23,7 @@ import org.bson.Document; import org.joda.time.DateTime; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.query.Update.Position; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java index fa98c5c735..8f48ddd054 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java @@ -31,7 +31,7 @@ import java.util.Set; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.*; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java index c338520b26..f63f4a1d4a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaPropertyUnitTests.java @@ -17,7 +17,7 @@ import static org.springframework.data.mongodb.test.util.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java index 92ce97149b..de963599bd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaUnitTests.java @@ -23,9 +23,9 @@ import java.util.UUID; import org.bson.Document; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; /** * Unit tests for {@link MongoJsonSchema}. @@ -33,11 +33,11 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class MongoJsonSchemaUnitTests { +@ExtendWith(MockitoExtension.class) +class MongoJsonSchemaUnitTests { @Test // DATAMONGO-1835 - public void toDocumentRendersSchemaCorrectly() { + void toDocumentRendersSchemaCorrectly() { MongoJsonSchema schema = MongoJsonSchema.builder() // .required("firstname", "lastname") // @@ -48,7 +48,7 @@ public void toDocumentRendersSchemaCorrectly() { } @Test // DATAMONGO-1835 - public void rendersDocumentBasedSchemaCorrectly() { + void rendersDocumentBasedSchemaCorrectly() { Document document = MongoJsonSchema.builder() // .required("firstname", "lastname") // @@ -61,7 +61,7 @@ public void rendersDocumentBasedSchemaCorrectly() { } @Test // DATAMONGO-1849 - public void rendersRequiredPropertiesCorrectly() { + void rendersRequiredPropertiesCorrectly() { MongoJsonSchema schema = MongoJsonSchema.builder() // .required("firstname") // @@ -75,7 +75,7 @@ public void rendersRequiredPropertiesCorrectly() { } @Test // DATAMONGO-2306 - public void rendersEncryptedPropertyCorrectly() { + void rendersEncryptedPropertyCorrectly() { MongoJsonSchema schema = MongoJsonSchema.builder().properties( // encrypted(string("ssn")) // @@ -90,7 +90,7 @@ public void rendersEncryptedPropertyCorrectly() { } @Test // DATAMONGO-2306 - public void rendersEncryptedPropertyWithKeyIdCorrectly() { + void rendersEncryptedPropertyWithKeyIdCorrectly() { UUID uuid = UUID.randomUUID(); MongoJsonSchema schema = MongoJsonSchema.builder().properties( // @@ -106,12 +106,12 @@ public void rendersEncryptedPropertyWithKeyIdCorrectly() { } @Test // DATAMONGO-1835 - public void throwsExceptionOnNullRoot() { + void throwsExceptionOnNullRoot() { assertThatIllegalArgumentException().isThrownBy(() -> MongoJsonSchema.of((JsonSchemaObject) null)); } @Test // DATAMONGO-1835 - public void throwsExceptionOnNullDocument() { + void throwsExceptionOnNullDocument() { assertThatIllegalArgumentException().isThrownBy(() -> MongoJsonSchema.of((Document) null)); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java index 2a3a4a99ed..91a7d1eb01 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/ExecutableMongoScriptUnitTests.java @@ -17,55 +17,32 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import org.springframework.util.ObjectUtils; +import org.junit.jupiter.api.Test; /** * @author Christoph Strobl */ -public class ExecutableMongoScriptUnitTests { - - public @Rule ExpectedException expectedException = ExpectedException.none(); +class ExecutableMongoScriptUnitTests { @Test // DATAMONGO-479 - public void constructorShouldThrowExceptionWhenRawScriptIsNull() { - - expectException(IllegalArgumentException.class, "must not be", "null"); - - new ExecutableMongoScript(null); + void constructorShouldThrowExceptionWhenRawScriptIsNull() { + assertThatIllegalArgumentException().isThrownBy(() -> new ExecutableMongoScript(null)) + .withMessageContaining("must not be").withMessageContaining("null"); } @Test // DATAMONGO-479 - public void constructorShouldThrowExceptionWhenRawScriptIsEmpty() { - - expectException(IllegalArgumentException.class, "must not be", "empty"); - - new ExecutableMongoScript(""); + void constructorShouldThrowExceptionWhenRawScriptIsEmpty() { + assertThatIllegalArgumentException().isThrownBy(() -> new ExecutableMongoScript("")) + .withMessageContaining("must not be").withMessageContaining("empty"); } @Test // DATAMONGO-479 - public void getCodeShouldReturnCodeRepresentationOfRawScript() { + void getCodeShouldReturnCodeRepresentationOfRawScript() { String jsFunction = "function(x) { return x; }"; ExecutableMongoScript script = new ExecutableMongoScript(jsFunction); - assertThat(script.getCode()).isNotNull(); - assertThat(script.getCode().toString()).isEqualTo(jsFunction); + assertThat(script.getCode()).isNotNull().hasToString(jsFunction); } - - private void expectException(Class type, String... messageFragments) { - - expectedException.expect(IllegalArgumentException.class); - - if (!ObjectUtils.isEmpty(messageFragments)) { - for (String fragment : messageFragments) { - expectedException.expectMessage(fragment); - } - } - } - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java index b11bd78cc2..cb8e01dd2a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/script/NamedMongoScriptUnitTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link NamedMongoScript}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java index 81d34fea18..2aa07e1965 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/spel/ExpressionNodeUnitTests.java @@ -20,11 +20,11 @@ import java.util.Arrays; import java.util.Collection; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.SpelNode; @@ -38,8 +38,8 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class ExpressionNodeUnitTests { +@ExtendWith(MockitoExtension.class) +class ExpressionNodeUnitTests { @Mock ExpressionState state; @@ -48,15 +48,15 @@ public class ExpressionNodeUnitTests { @Mock OpDivide divide; @Mock OpMultiply multiply; - Collection operators; + private Collection operators; - @Before - public void setUp() { + @BeforeEach + void setUp() { this.operators = Arrays.asList(minus, plus, divide, multiply); } @Test // DATAMONGO-774 - public void createsOperatorNodeForOperations() { + void createsOperatorNodeForOperations() { for (SpelNode operator : operators) { assertThat(ExpressionNode.from(operator, state)).isInstanceOf(OperatorNode.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java index ebd29428ad..859c04acb8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorUnitTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.*; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.query.Criteria; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java index 59c4ef1451..8e9d7d2c90 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/AntPathUnitTests.java @@ -19,7 +19,7 @@ import java.util.regex.Pattern; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link AntPath}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java index af3d35348a..b248375177 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java @@ -22,7 +22,7 @@ import org.bson.BsonObjectId; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.mongodb.MongoGridFSException; import com.mongodb.client.gridfs.model.GridFSFile; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java index 2143cbc5fb..88731442c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java @@ -25,8 +25,8 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.core.Constants; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mongodb.core.MongoTemplate; @@ -73,7 +73,7 @@ public class PerformanceTests { PersonRepository repository; MongoConverter converter; - @Before + @BeforeEach public void setUp() throws Exception { this.mongo = MongoClients.create(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java index 86487164a9..0e72c812a2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java @@ -28,8 +28,9 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import org.springframework.core.Constants; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mongodb.core.ReactiveMongoOperations; @@ -82,7 +83,7 @@ public class ReactivePerformanceTests { ReactivePersonRepository repository; MongoConverter converter; - @Before + @BeforeEach public void setUp() throws Exception { mongo = MongoClients.create(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 52446d4405..2a9f98d1b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -97,17 +98,22 @@ public void setUp() throws InterruptedException { oliver = new Person("Oliver August", "Matthews", 4); carter = new Person("Carter", "Beauford", 49); carter.setSkills(Arrays.asList("Drums", "percussion", "vocals")); - Thread.sleep(10); + boyd = new Person("Boyd", "Tinsley", 45); boyd.setSkills(Arrays.asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); stefan = new Person("Stefan", "Lessard", 34); leroi = new Person("Leroi", "Moore", 41); - alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); - person = new QPerson("person"); - all = repository.saveAll(Arrays.asList(oliver, dave, carter, boyd, stefan, leroi, alicia)); + Arrays.asList(boyd, stefan, leroi, alicia).forEach(it -> { + it.createdAt = new Date(dave.createdAt.getTime() + 1000L); + }); + + List toSave = asList(oliver, dave, carter, boyd, stefan, leroi, alicia); + toSave.forEach(it -> it.setId(null)); + + all = repository.saveAll(toSave); } @Test @@ -142,7 +148,7 @@ public void deletesPersonCorrectly() { @Test public void deletesPersonByIdCorrectly() { - repository.deleteById(dave.getId().toString()); + repository.deleteById(dave.getId()); List result = repository.findAll(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java index d3fda4c782..2edfd08b7d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Contact.java @@ -36,4 +36,8 @@ public Contact() { public String getId() { return id; } + + public void setId(String id) { + this.id = id; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java index 5c3a63c331..decd3d39cf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/CdiExtensionIntegrationTests.java @@ -20,9 +20,9 @@ import javax.enterprise.inject.se.SeContainer; import javax.enterprise.inject.se.SeContainerInitializer; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.repository.Person; @@ -36,7 +36,7 @@ public class CdiExtensionIntegrationTests { static SeContainer container; - @BeforeClass + @BeforeAll public static void setUp() { container = SeContainerInitializer.newInstance() // @@ -45,7 +45,7 @@ public static void setUp() { .initialize(); } - @AfterClass + @AfterAll public static void tearDown() { container.close(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java index 10f09722e7..761f7a020a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtensionUnitTests.java @@ -19,7 +19,7 @@ import java.util.Collection; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java index 3850973980..b13308e1e6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtensionUnitTests.java @@ -19,7 +19,7 @@ import java.util.Collection; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; 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 175c6eeb4c..216ba31147 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 @@ -26,13 +26,15 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -72,8 +74,9 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class AbstractMongoQueryUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class AbstractMongoQueryUnitTests { @Mock MongoOperations mongoOperationsMock; @Mock ExecutableFind executableFind; @@ -82,8 +85,8 @@ public class AbstractMongoQueryUnitTests { @Mock MongoMappingContext mappingContextMock; @Mock DeleteResult deleteResultMock; - @Before - public void setUp() { + @BeforeEach + void setUp() { doReturn("persons").when(persitentEntityMock).getCollection(); doReturn(persitentEntityMock).when(mappingContextMock).getPersistentEntity(Mockito.any(Class.class)); @@ -103,7 +106,7 @@ public void setUp() { } @Test // DATAMONGO-566 - public void testDeleteExecutionCallsRemoveCorrectly() { + void testDeleteExecutionCallsRemoveCorrectly() { createQueryForMethod("deletePersonByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" }); @@ -112,7 +115,7 @@ public void testDeleteExecutionCallsRemoveCorrectly() { } @Test // DATAMONGO-566, DATAMONGO-1040 - public void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollectionLike() { + void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollectionLike() { createQueryForMethod("deleteByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" }); @@ -120,7 +123,7 @@ public void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollec } @Test // DATAMONGO-566 - public void testDeleteExecutionReturnsZeroWhenWriteResultIsNull() { + void testDeleteExecutionReturnsZeroWhenWriteResultIsNull() { MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class); query.setDeleteQuery(true); @@ -129,7 +132,7 @@ public void testDeleteExecutionReturnsZeroWhenWriteResultIsNull() { } @Test // DATAMONGO-566, DATAMONGO-978 - public void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() { + void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() { when(deleteResultMock.getDeletedCount()).thenReturn(100L); when(deleteResultMock.wasAcknowledged()).thenReturn(true); @@ -142,7 +145,7 @@ public void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() { } @Test // DATAMONGO-957 - public void metadataShouldNotBeAddedToQueryWhenNotPresent() { + void metadataShouldNotBeAddedToQueryWhenNotPresent() { MongoQueryFake query = createQueryForMethod("findByFirstname", String.class); query.execute(new Object[] { "fake" }); @@ -157,7 +160,7 @@ public void metadataShouldNotBeAddedToQueryWhenNotPresent() { } @Test // DATAMONGO-957 - public void metadataShouldBeAddedToQueryCorrectly() { + void metadataShouldBeAddedToQueryCorrectly() { MongoQueryFake query = createQueryForMethod("findByFirstname", String.class, Pageable.class); query.execute(new Object[] { "fake", PageRequest.of(0, 10) }); @@ -171,7 +174,7 @@ public void metadataShouldBeAddedToQueryCorrectly() { } @Test // DATAMONGO-957 - public void metadataShouldBeAddedToCountQueryCorrectly() { + void metadataShouldBeAddedToCountQueryCorrectly() { MongoQueryFake query = createQueryForMethod("findByFirstname", String.class, Pageable.class); query.execute(new Object[] { "fake", PageRequest.of(1, 10) }); @@ -185,7 +188,7 @@ public void metadataShouldBeAddedToCountQueryCorrectly() { } @Test // DATAMONGO-957, DATAMONGO-1783 - public void metadataShouldBeAddedToStringBasedQueryCorrectly() { + void metadataShouldBeAddedToStringBasedQueryCorrectly() { MongoQueryFake query = createQueryForMethod("findByAnnotatedQuery", String.class, Pageable.class); query.execute(new Object[] { "fake", PageRequest.of(0, 10) }); @@ -199,7 +202,7 @@ public void metadataShouldBeAddedToStringBasedQueryCorrectly() { } @Test // DATAMONGO-1057 - public void slicedExecutionShouldRetainNrOfElementsToSkip() { + void slicedExecutionShouldRetainNrOfElementsToSkip() { MongoQueryFake query = createQueryForMethod("findByLastname", String.class, Pageable.class); Pageable page1 = PageRequest.of(0, 10); @@ -218,7 +221,7 @@ public void slicedExecutionShouldRetainNrOfElementsToSkip() { } @Test // DATAMONGO-1057 - public void slicedExecutionShouldIncrementLimitByOne() { + void slicedExecutionShouldIncrementLimitByOne() { MongoQueryFake query = createQueryForMethod("findByLastname", String.class, Pageable.class); Pageable page1 = PageRequest.of(0, 10); @@ -237,7 +240,7 @@ public void slicedExecutionShouldIncrementLimitByOne() { } @Test // DATAMONGO-1057 - public void slicedExecutionShouldRetainSort() { + void slicedExecutionShouldRetainSort() { MongoQueryFake query = createQueryForMethod("findByLastname", String.class, Pageable.class); Pageable page1 = PageRequest.of(0, 10, Sort.Direction.DESC, "bar"); @@ -257,7 +260,7 @@ public void slicedExecutionShouldRetainSort() { } @Test // DATAMONGO-1080 - public void doesNotTryToPostProcessQueryResultIntoWrapperType() { + void doesNotTryToPostProcessQueryResultIntoWrapperType() { Person reference = new Person(); @@ -269,7 +272,7 @@ public void doesNotTryToPostProcessQueryResultIntoWrapperType() { } @Test // DATAMONGO-1865 - public void limitingSingleEntityQueryCallsFirst() { + void limitingSingleEntityQueryCallsFirst() { Person reference = new Person(); @@ -281,7 +284,7 @@ public void limitingSingleEntityQueryCallsFirst() { } @Test // DATAMONGO-1872 - public void doesNotFixCollectionOnPreparation() { + void doesNotFixCollectionOnPreparation() { AbstractMongoQuery query = createQueryForMethod(DynamicallyMappedRepository.class, "findBy"); @@ -292,7 +295,7 @@ public void doesNotFixCollectionOnPreparation() { } @Test // DATAMONGO-1979 - public void usesAnnotatedSortWhenPresent() { + void usesAnnotatedSortWhenPresent() { createQueryForMethod("findByAge", Integer.class) // .execute(new Object[] { 1000 }); @@ -303,7 +306,7 @@ public void usesAnnotatedSortWhenPresent() { } @Test // DATAMONGO-1979 - public void usesExplicitSortOverridesAnnotatedSortWhenPresent() { + void usesExplicitSortOverridesAnnotatedSortWhenPresent() { createQueryForMethod("findByAge", Integer.class, Sort.class) // .execute(new Object[] { 1000, Sort.by(Direction.DESC, "age") }); @@ -314,7 +317,7 @@ public void usesExplicitSortOverridesAnnotatedSortWhenPresent() { } @Test // DATAMONGO-1854 - public void shouldApplyStaticAnnotatedCollation() { + void shouldApplyStaticAnnotatedCollation() { createQueryForMethod("findWithCollationUsingSpimpleStringValueByFirstName", String.class) // .execute(new Object[] { "dalinar" }); @@ -326,7 +329,7 @@ public void shouldApplyStaticAnnotatedCollation() { } @Test // DATAMONGO-1854 - public void shouldApplyStaticAnnotatedCollationAsDocument() { + void shouldApplyStaticAnnotatedCollationAsDocument() { createQueryForMethod("findWithCollationUsingDocumentByFirstName", String.class) // .execute(new Object[] { "dalinar" }); @@ -338,7 +341,7 @@ public void shouldApplyStaticAnnotatedCollationAsDocument() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationAsString() { + void shouldApplyDynamicAnnotatedCollationAsString() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // .execute(new Object[] { "dalinar", "en_US" }); @@ -350,7 +353,7 @@ public void shouldApplyDynamicAnnotatedCollationAsString() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationAsDocument() { + void shouldApplyDynamicAnnotatedCollationAsDocument() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // .execute(new Object[] { "dalinar", new Document("locale", "en_US") }); @@ -362,7 +365,7 @@ public void shouldApplyDynamicAnnotatedCollationAsDocument() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationAsLocale() { + void shouldApplyDynamicAnnotatedCollationAsLocale() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // .execute(new Object[] { "dalinar", Locale.US }); @@ -373,20 +376,18 @@ public void shouldApplyDynamicAnnotatedCollationAsLocale() { .contains(Collation.of("en_US").toDocument()); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-1854 - public void shouldThrowExceptionOnNonParsableCollation() { + @Test // DATAMONGO-1854 + void shouldThrowExceptionOnNonParsableCollation() { - createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // - .execute(new Object[] { "dalinar", 100 }); + assertThatIllegalArgumentException().isThrownBy(() -> { - ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); - verify(withQueryMock).matching(captor.capture()); - assertThat(captor.getValue().getCollation().map(Collation::toDocument)) - .contains(Collation.of("en_US").toDocument()); + createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // + .execute(new Object[] { "dalinar", 100 }); + }); } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationIn() { + void shouldApplyDynamicAnnotatedCollationIn() { createQueryForMethod("findWithCollationUsingPlaceholderInDocumentByFirstName", String.class, String.class) // .execute(new Object[] { "dalinar", "en_US" }); @@ -398,7 +399,7 @@ public void shouldApplyDynamicAnnotatedCollationIn() { } @Test // DATAMONGO-1854 - public void shouldApplyCollationParameter() { + void shouldApplyCollationParameter() { Collation collation = Collation.of("en_US"); createQueryForMethod("findWithCollationParameterByFirstName", String.class, Collation.class) // @@ -410,7 +411,7 @@ public void shouldApplyCollationParameter() { } @Test // DATAMONGO-1854 - public void collationParameterShouldOverrideAnnotation() { + void collationParameterShouldOverrideAnnotation() { Collation collation = Collation.of("de_AT"); createQueryForMethod("findWithWithCollationParameterAndAnnotationByFirstName", String.class, Collation.class) // @@ -422,7 +423,7 @@ public void collationParameterShouldOverrideAnnotation() { } @Test // DATAMONGO-1854 - public void collationParameterShouldNotBeAppliedWhenNullOverrideAnnotation() { + void collationParameterShouldNotBeAppliedWhenNullOverrideAnnotation() { createQueryForMethod("findWithWithCollationParameterAndAnnotationByFirstName", String.class, Collation.class) // .execute(new Object[] { "dalinar", null }); @@ -457,7 +458,7 @@ private static class MongoQueryFake extends AbstractMongoQuery { private boolean isDeleteQuery; private boolean isLimitingQuery; - public MongoQueryFake(MongoQueryMethod method, MongoOperations operations) { + MongoQueryFake(MongoQueryMethod method, MongoOperations operations) { super(method, operations, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT); } @@ -486,12 +487,12 @@ protected boolean isLimiting() { return isLimitingQuery; } - public MongoQueryFake setDeleteQuery(boolean isDeleteQuery) { + MongoQueryFake setDeleteQuery(boolean isDeleteQuery) { this.isDeleteQuery = isDeleteQuery; return this; } - public MongoQueryFake setLimitingQuery(boolean limitingQuery) { + MongoQueryFake setLimitingQuery(boolean limitingQuery) { isLimitingQuery = limitingQuery; return this; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java index dc69a8f786..38e9a08071 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java @@ -23,13 +23,16 @@ import java.util.Locale; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithQuery; import org.springframework.data.mongodb.core.ReactiveFindOperation.ReactiveFind; @@ -52,8 +55,9 @@ * @author Christoph Strobl * @currentRead Way of Kings - Brandon Sanderson */ -@RunWith(MockitoJUnitRunner.class) -public class AbstractReactiveMongoQueryUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class AbstractReactiveMongoQueryUnitTests { @Mock ReactiveMongoOperations mongoOperationsMock; @Mock BasicMongoPersistentEntity persitentEntityMock; @@ -62,8 +66,8 @@ public class AbstractReactiveMongoQueryUnitTests { @Mock ReactiveFind executableFind; @Mock FindWithQuery withQueryMock; - @Before - public void setUp() { + @BeforeEach + void setUp() { doReturn("persons").when(persitentEntityMock).getCollection(); doReturn(persitentEntityMock).when(mappingContextMock).getPersistentEntity(Mockito.any(Class.class)); @@ -81,7 +85,7 @@ public void setUp() { } @Test // DATAMONGO-1854 - public void shouldApplyStaticAnnotatedCollation() { + void shouldApplyStaticAnnotatedCollation() { createQueryForMethod("findWithCollationUsingSpimpleStringValueByFirstName", String.class) // .execute(new Object[] { "dalinar" }); @@ -93,7 +97,7 @@ public void shouldApplyStaticAnnotatedCollation() { } @Test // DATAMONGO-1854 - public void shouldApplyStaticAnnotatedCollationAsDocument() { + void shouldApplyStaticAnnotatedCollationAsDocument() { createQueryForMethod("findWithCollationUsingDocumentByFirstName", String.class) // .execute(new Object[] { "dalinar" }); @@ -105,7 +109,7 @@ public void shouldApplyStaticAnnotatedCollationAsDocument() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationAsString() { + void shouldApplyDynamicAnnotatedCollationAsString() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // .execute(new Object[] { "dalinar", "en_US" }); @@ -117,7 +121,7 @@ public void shouldApplyDynamicAnnotatedCollationAsString() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationAsDocument() { + void shouldApplyDynamicAnnotatedCollationAsDocument() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // .execute(new Object[] { "dalinar", new Document("locale", "en_US") }); @@ -129,7 +133,7 @@ public void shouldApplyDynamicAnnotatedCollationAsDocument() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationAsLocale() { + void shouldApplyDynamicAnnotatedCollationAsLocale() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // .execute(new Object[] { "dalinar", Locale.US }); @@ -140,20 +144,17 @@ public void shouldApplyDynamicAnnotatedCollationAsLocale() { .contains(Collation.of("en_US").toDocument()); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-1854 - public void shouldThrowExceptionOnNonParsableCollation() { - - createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // - .execute(new Object[] { "dalinar", 100 }); + @Test // DATAMONGO-1854 + void shouldThrowExceptionOnNonParsableCollation() { - ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); - verify(withQueryMock).matching(captor.capture()); - assertThat(captor.getValue().getCollation().map(Collation::toDocument)) - .contains(Collation.of("en_US").toDocument()); + assertThatIllegalArgumentException().isThrownBy(() -> { + createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // + .execute(new Object[] { "dalinar", 100 }); + }); } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationIn() { + void shouldApplyDynamicAnnotatedCollationIn() { createQueryForMethod("findWithCollationUsingPlaceholderInDocumentByFirstName", String.class, String.class) // .execute(new Object[] { "dalinar", "en_US" }); @@ -165,7 +166,7 @@ public void shouldApplyDynamicAnnotatedCollationIn() { } @Test // DATAMONGO-1854 - public void shouldApplyDynamicAnnotatedCollationWithMultiplePlaceholders() { + void shouldApplyDynamicAnnotatedCollationWithMultiplePlaceholders() { createQueryForMethod("findWithCollationUsingPlaceholdersInDocumentByFirstName", String.class, String.class, int.class) // @@ -178,7 +179,7 @@ public void shouldApplyDynamicAnnotatedCollationWithMultiplePlaceholders() { } @Test // DATAMONGO-1854 - public void shouldApplyCollationParameter() { + void shouldApplyCollationParameter() { Collation collation = Collation.of("en_US"); createQueryForMethod("findWithCollationParameterByFirstName", String.class, Collation.class) // @@ -190,7 +191,7 @@ public void shouldApplyCollationParameter() { } @Test // DATAMONGO-1854 - public void collationParameterShouldOverrideAnnotation() { + void collationParameterShouldOverrideAnnotation() { Collation collation = Collation.of("de_AT"); createQueryForMethod("findWithWithCollationParameterAndAnnotationByFirstName", String.class, Collation.class) // @@ -202,7 +203,7 @@ public void collationParameterShouldOverrideAnnotation() { } @Test // DATAMONGO-1854 - public void collationParameterShouldNotBeAppliedWhenNullOverrideAnnotation() { + void collationParameterShouldNotBeAppliedWhenNullOverrideAnnotation() { createQueryForMethod("findWithWithCollationParameterAndAnnotationByFirstName", String.class, Collation.class) // .execute(new Object[] { "dalinar", null }); @@ -237,7 +238,7 @@ private static class ReactiveMongoQueryFake extends AbstractReactiveMongoQuery { private boolean isDeleteQuery; private boolean isLimitingQuery; - public ReactiveMongoQueryFake(ReactiveMongoQueryMethod method, ReactiveMongoOperations operations) { + ReactiveMongoQueryFake(ReactiveMongoQueryMethod method, ReactiveMongoOperations operations) { super(method, operations, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java index 0e211ac5cb..ce192ee8e4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java @@ -21,11 +21,11 @@ import java.util.Arrays; import java.util.Collection; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -45,7 +45,7 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ConvertingParameterAccessorUnitTests { @Mock MongoDatabaseFactory factory; @@ -55,7 +55,7 @@ public class ConvertingParameterAccessorUnitTests { MappingMongoConverter converter; DbRefResolver resolver; - @Before + @BeforeEach public void setUp() { this.context = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java index 94f6e985a1..b3ceb0d0ab 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MappingMongoEntityInformationUnitTests.java @@ -20,10 +20,10 @@ import lombok.Value; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.Persistable; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -36,7 +36,7 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MappingMongoEntityInformationUnitTests { @Mock MongoPersistentEntity info; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java index fce0af05af..e6ed526653 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java @@ -21,7 +21,7 @@ import java.util.List; import org.bson.Document; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; import org.springframework.data.geo.Distance; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java index dc5e391e78..b642ac817c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersUnitTests.java @@ -20,10 +20,11 @@ import java.lang.reflect.Method; import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.domain.Range; import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResults; @@ -40,13 +41,13 @@ * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class MongoParametersUnitTests { +@ExtendWith(MockitoExtension.class) +class MongoParametersUnitTests { @Mock MongoQueryMethod queryMethod; @Test - public void discoversDistanceParameter() throws NoSuchMethodException, SecurityException { + void discoversDistanceParameter() throws NoSuchMethodException, SecurityException { Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class); MongoParameters parameters = new MongoParameters(method, false); @@ -62,36 +63,38 @@ public void discoversDistanceParameter() throws NoSuchMethodException, SecurityE } @Test - public void doesNotConsiderPointAsNearForSimpleQuery() throws Exception { + void doesNotConsiderPointAsNearForSimpleQuery() throws Exception { Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class); MongoParameters parameters = new MongoParameters(method, false); assertThat(parameters.getNearIndex()).isEqualTo(-1); } - @Test(expected = IllegalStateException.class) - public void rejectsMultiplePointsForGeoNearMethod() throws Exception { + @Test + void rejectsMultiplePointsForGeoNearMethod() throws Exception { Method method = PersonRepository.class.getMethod("findByLocationNearAndOtherLocation", Point.class, Point.class); - new MongoParameters(method, true); + + assertThatIllegalStateException().isThrownBy(() -> new MongoParameters(method, true)); } - @Test(expected = IllegalStateException.class) - public void rejectsMultipleDoubleArraysForGeoNearMethod() throws Exception { + @Test + void rejectsMultipleDoubleArraysForGeoNearMethod() throws Exception { Method method = PersonRepository.class.getMethod("invalidDoubleArrays", double[].class, double[].class); - new MongoParameters(method, true); + + assertThatIllegalStateException().isThrownBy(() -> new MongoParameters(method, true)); } @Test - public void doesNotRejectMultiplePointsForSimpleQueryMethod() throws Exception { + void doesNotRejectMultiplePointsForSimpleQueryMethod() throws Exception { Method method = PersonRepository.class.getMethod("someOtherMethod", Point.class, Point.class); new MongoParameters(method, false); } @Test - public void findsAnnotatedPointForGeoNearQuery() throws Exception { + void findsAnnotatedPointForGeoNearQuery() throws Exception { Method method = PersonRepository.class.getMethod("findByOtherLocationAndLocationNear", Point.class, Point.class); MongoParameters parameters = new MongoParameters(method, true); @@ -99,7 +102,7 @@ public void findsAnnotatedPointForGeoNearQuery() throws Exception { } @Test - public void findsAnnotatedDoubleArrayForGeoNearQuery() throws Exception { + void findsAnnotatedDoubleArrayForGeoNearQuery() throws Exception { Method method = PersonRepository.class.getMethod("validDoubleArrays", double[].class, double[].class); MongoParameters parameters = new MongoParameters(method, true); @@ -107,7 +110,7 @@ public void findsAnnotatedDoubleArrayForGeoNearQuery() throws Exception { } @Test // DATAMONGO-973 - public void shouldFindTextCriteriaAtItsIndex() throws SecurityException, NoSuchMethodException { + void shouldFindTextCriteriaAtItsIndex() throws SecurityException, NoSuchMethodException { Method method = PersonRepository.class.getMethod("findByNameAndText", String.class, TextCriteria.class); MongoParameters parameters = new MongoParameters(method, false); @@ -115,7 +118,7 @@ public void shouldFindTextCriteriaAtItsIndex() throws SecurityException, NoSuchM } @Test // DATAMONGO-973 - public void shouldTreatTextCriteriaParameterAsSpecialParameter() throws SecurityException, NoSuchMethodException { + void shouldTreatTextCriteriaParameterAsSpecialParameter() throws SecurityException, NoSuchMethodException { Method method = PersonRepository.class.getMethod("findByNameAndText", String.class, TextCriteria.class); MongoParameters parameters = new MongoParameters(method, false); @@ -123,7 +126,7 @@ public void shouldTreatTextCriteriaParameterAsSpecialParameter() throws Security } @Test // DATAMONGO-1110 - public void shouldFindMinAndMaxDistanceParameters() throws NoSuchMethodException, SecurityException { + void shouldFindMinAndMaxDistanceParameters() throws NoSuchMethodException, SecurityException { Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Range.class); MongoParameters parameters = new MongoParameters(method, false); @@ -133,8 +136,7 @@ public void shouldFindMinAndMaxDistanceParameters() throws NoSuchMethodException } @Test // DATAMONGO-1110 - public void shouldNotHaveMinDistanceIfOnlyOneDistanceParameterPresent() - throws NoSuchMethodException, SecurityException { + void shouldNotHaveMinDistanceIfOnlyOneDistanceParameterPresent() throws NoSuchMethodException, SecurityException { Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class); MongoParameters parameters = new MongoParameters(method, false); @@ -144,7 +146,7 @@ public void shouldNotHaveMinDistanceIfOnlyOneDistanceParameterPresent() } @Test // DATAMONGO-1854 - public void shouldReturnMinusOneIfCollationParameterDoesNotExist() throws NoSuchMethodException, SecurityException { + void shouldReturnMinusOneIfCollationParameterDoesNotExist() throws NoSuchMethodException, SecurityException { Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class); MongoParameters parameters = new MongoParameters(method, false); @@ -153,7 +155,7 @@ public void shouldReturnMinusOneIfCollationParameterDoesNotExist() throws NoSuch } @Test // DATAMONGO-1854 - public void shouldReturnIndexOfCollationParameterIfExists() throws NoSuchMethodException, SecurityException { + void shouldReturnIndexOfCollationParameterIfExists() throws NoSuchMethodException, SecurityException { Method method = PersonRepository.class.getMethod("findByText", String.class, Collation.class); MongoParameters parameters = new MongoParameters(method, false); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java index 36e59b6135..942c888303 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java @@ -23,11 +23,11 @@ import java.util.Arrays; import java.util.Collections; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -71,8 +71,8 @@ * @author Christoph Strobl * @soundtrack U Can't Touch This - MC Hammer */ -@RunWith(MockitoJUnitRunner.class) -public class MongoQueryExecutionUnitTests { +@ExtendWith(MockitoExtension.class) +class MongoQueryExecutionUnitTests { @Mock MongoOperations mongoOperationsMock; @Mock ExecutableFind findOperationMock; @@ -81,28 +81,28 @@ public class MongoQueryExecutionUnitTests { @Mock TerminatingFindNear terminatingGeoMock; @Mock DbRefResolver dbRefResolver; - SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); - Point POINT = new Point(10, 20); - Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS); - RepositoryMetadata metadata = new DefaultRepositoryMetadata(PersonRepository.class); - MongoMappingContext context = new MongoMappingContext(); - ProjectionFactory factory = new SpelAwareProxyProjectionFactory(); - Method method = ReflectionUtils.findMethod(PersonRepository.class, "findByLocationNear", Point.class, Distance.class, + private SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); + private Point POINT = new Point(10, 20); + private Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS); + private RepositoryMetadata metadata = new DefaultRepositoryMetadata(PersonRepository.class); + private MongoMappingContext context = new MongoMappingContext(); + private ProjectionFactory factory = new SpelAwareProxyProjectionFactory(); + private Method method = ReflectionUtils.findMethod(PersonRepository.class, "findByLocationNear", Point.class, + Distance.class, Pageable.class); - MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); - MappingMongoConverter converter; + private MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); + private MappingMongoConverter converter; - @Before + @BeforeEach @SuppressWarnings("unchecked") - public void setUp() { + void setUp() { converter = new MappingMongoConverter(dbRefResolver, context); - when(mongoOperationsMock.getConverter()).thenReturn(converter); - when(mongoOperationsMock.query(any(Class.class))).thenReturn(findOperationMock); + } @Test // DATAMONGO-1464 - public void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() { + void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() { doReturn(terminatingMock).when(operationMock).matching(any(Query.class)); doReturn(Collections.emptyList()).when(terminatingMock).all(); @@ -115,7 +115,7 @@ public void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() } @Test // DATAMONGO-1464 - public void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() { + void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() { doReturn(terminatingMock).when(operationMock).matching(any(Query.class)); doReturn(Arrays.asList(new Person(), new Person(), new Person(), new Person())).when(terminatingMock).all(); @@ -128,7 +128,7 @@ public void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPage } @Test // DATAMONGO-1464 - public void pagedExecutionRetrievesObjectsForPageableOutOfRange() { + void pagedExecutionRetrievesObjectsForPageableOutOfRange() { doReturn(terminatingMock).when(operationMock).matching(any(Query.class)); doReturn(Collections.emptyList()).when(terminatingMock).all(); @@ -141,9 +141,11 @@ public void pagedExecutionRetrievesObjectsForPageableOutOfRange() { } @Test // DATAMONGO-1464 - public void pagingGeoExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() { + void pagingGeoExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() { GeoResult result = new GeoResult<>(new Person(), DISTANCE); + when(mongoOperationsMock.getConverter()).thenReturn(converter); + when(mongoOperationsMock.query(any(Class.class))).thenReturn(findOperationMock); when(findOperationMock.near(any(NearQuery.class))).thenReturn(terminatingGeoMock); doReturn(new GeoResults<>(Arrays.asList(result, result, result, result))).when(terminatingGeoMock).all(); @@ -160,8 +162,10 @@ public void pagingGeoExecutionShouldUseCountFromResultWithOffsetAndResultsWithin } @Test // DATAMONGO-1464 - public void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() { + void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() { + when(mongoOperationsMock.getConverter()).thenReturn(converter); + when(mongoOperationsMock.query(any(Class.class))).thenReturn(findOperationMock); when(findOperationMock.near(any(NearQuery.class))).thenReturn(terminatingGeoMock); doReturn(new GeoResults<>(Collections.emptyList())).when(terminatingGeoMock).all(); doReturn(terminatingMock).when(findOperationMock).matching(any(Query.class)); @@ -180,7 +184,7 @@ public void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() { } @Test // DATAMONGO-2351 - public void acknowledgedDeleteReturnsDeletedCount() { + void acknowledgedDeleteReturnsDeletedCount() { Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteAllByLastname", String.class); MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); @@ -192,7 +196,7 @@ public void acknowledgedDeleteReturnsDeletedCount() { } @Test // DATAMONGO-2351 - public void unacknowledgedDeleteReturnsZeroDeletedCount() { + void unacknowledgedDeleteReturnsZeroDeletedCount() { Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteAllByLastname", String.class); MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); @@ -204,7 +208,7 @@ public void unacknowledgedDeleteReturnsZeroDeletedCount() { } @Test // DATAMONGO-1997 - public void deleteExecutionWithEntityReturnTypeTriggersFindAndRemove() { + void deleteExecutionWithEntityReturnTypeTriggersFindAndRemove() { Method method = ReflectionUtils.findMethod(PersonRepository.class, "deleteByLastname", String.class); MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java index 4349f76004..46d4e2de54 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java @@ -24,11 +24,11 @@ import org.bson.Document; import org.bson.json.JsonParseException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -58,7 +58,7 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class PartTreeMongoQueryUnitTests { @Mock MongoOperations mongoOperationsMock; @@ -66,7 +66,7 @@ public class PartTreeMongoQueryUnitTests { MongoMappingContext mappingContext; - @Before + @BeforeEach public void setUp() { mappingContext = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java index e5591d0317..909f832d98 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecutionUnitTests.java @@ -26,11 +26,11 @@ import java.lang.reflect.Method; import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.reactivestreams.Publisher; import org.springframework.data.domain.PageRequest; @@ -57,7 +57,7 @@ * @author Mark Paluch * @author Artyom Gabeev */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveMongoQueryExecutionUnitTests { @Mock private ReactiveMongoOperations operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java index 8565bb9800..f899f3c68f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java @@ -28,12 +28,12 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -66,7 +66,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveStringBasedAggregationUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -83,7 +83,7 @@ public class ReactiveStringBasedAggregationUnitTests { private static final Document SORT = Document.parse(RAW_SORT_STRING); private static final Document GROUP_BY_LASTNAME = Document.parse(RAW_GROUP_BY_LASTNAME_STRING); - @Before + @BeforeEach public void setUp() { converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java index e6a263c7c3..72eb4548fb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java @@ -27,11 +27,11 @@ import java.util.Map; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.ReactiveFindOperation.ReactiveFind; import org.springframework.data.mongodb.core.ReactiveMongoOperations; @@ -58,7 +58,7 @@ * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class ReactiveStringBasedMongoQueryUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -69,7 +69,7 @@ public class ReactiveStringBasedMongoQueryUnitTests { MongoConverter converter; - @Before + @BeforeEach public void setUp() { when(operations.query(any())).thenReturn(reactiveFind); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java index f1ba24abaf..568e455c7a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java @@ -28,12 +28,13 @@ import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoOperations; @@ -66,7 +67,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class StringBasedAggregationUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -84,7 +85,7 @@ public class StringBasedAggregationUnitTests { private static final Document SORT = Document.parse(RAW_SORT_STRING); private static final Document GROUP_BY_LASTNAME = Document.parse(RAW_GROUP_BY_LASTNAME_STRING); - @Before + @BeforeEach public void setUp() { converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 3a8a31ac8f..30b32cb915 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -33,11 +33,12 @@ import org.bson.UuidRepresentation; import org.bson.codecs.configuration.CodecRegistry; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.mongodb.core.DbCallback; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; @@ -70,7 +71,7 @@ * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class StringBasedMongoQueryUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -81,7 +82,7 @@ public class StringBasedMongoQueryUnitTests { MongoConverter converter; - @Before + @BeforeEach public void setUp() { this.converter = new MappingMongoConverter(factory, new MongoMappingContext()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java index c301b8a17c..9237d2f9c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListenerUnitTests.java @@ -21,13 +21,15 @@ import static org.mockito.Mockito.anyString; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.index.IndexDefinition; @@ -44,10 +46,11 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) -public class IndexEnsuringQueryCreationListenerUnitTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class IndexEnsuringQueryCreationListenerUnitTests { - IndexEnsuringQueryCreationListener listener; + private IndexEnsuringQueryCreationListener listener; @Mock IndexOperationsProvider provider; @Mock PartTree partTree; @@ -56,8 +59,8 @@ public class IndexEnsuringQueryCreationListenerUnitTests { @Mock IndexOperations indexOperations; @Mock MongoEntityMetadata entityInformation; - @Before - public void setUp() { + @BeforeEach + void setUp() { this.listener = new IndexEnsuringQueryCreationListener(provider); @@ -69,7 +72,7 @@ public void setUp() { } @Test // DATAMONGO-1753 - public void skipsQueryCreationForMethodWithoutPredicate() { + void skipsQueryCreationForMethodWithoutPredicate() { when(partTree.hasPredicate()).thenReturn(false); @@ -79,7 +82,7 @@ public void skipsQueryCreationForMethodWithoutPredicate() { } @Test // DATAMONGO-1854 - public void usesCollationWhenPresentAndFixedValue() { + void usesCollationWhenPresentAndFixedValue() { when(partTree.hasPredicate()).thenReturn(true); when(partTree.getParts()).thenReturn(Streamable.empty()); @@ -98,7 +101,7 @@ public void usesCollationWhenPresentAndFixedValue() { } @Test // DATAMONGO-1854 - public void usesCollationWhenPresentAndFixedDocumentValue() { + void usesCollationWhenPresentAndFixedDocumentValue() { when(partTree.hasPredicate()).thenReturn(true); when(partTree.getParts()).thenReturn(Streamable.empty()); @@ -117,7 +120,7 @@ public void usesCollationWhenPresentAndFixedDocumentValue() { } @Test // DATAMONGO-1854 - public void skipsCollationWhenPresentButDynamic() { + void skipsCollationWhenPresentButDynamic() { when(partTree.hasPredicate()).thenReturn(true); when(partTree.getParts()).thenReturn(Streamable.empty()); @@ -136,7 +139,7 @@ public void skipsCollationWhenPresentButDynamic() { } @Test // DATAMONGO-1854 - public void skipsCollationWhenNotPresent() { + void skipsCollationWhenNotPresent() { when(partTree.hasPredicate()).thenReturn(true); when(partTree.getParts()).thenReturn(Streamable.empty()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java index ea930c0c3b..538e8a458e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBeanUnitTests.java @@ -20,10 +20,10 @@ import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.MongoOperations; @@ -37,7 +37,7 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MongoRepositoryFactoryBeanUnitTests { @Mock MongoOperations operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java index 9b1863dbf9..17d55eec1d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryUnitTests.java @@ -20,11 +20,11 @@ import java.io.Serializable; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.MongoTemplate; @@ -39,7 +39,7 @@ * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class MongoRepositoryFactoryUnitTests { @Mock MongoTemplate template; @@ -50,7 +50,7 @@ public class MongoRepositoryFactoryUnitTests { @Mock @SuppressWarnings("rawtypes") MongoPersistentEntity entity; - @Before + @BeforeEach @SuppressWarnings("unchecked") public void setUp() { when(template.getConverter()).thenReturn(converter); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java index eaddc42b0a..f45772878b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryUnitTests.java @@ -19,12 +19,12 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.Example; import org.springframework.data.domain.PageRequest; @@ -37,14 +37,14 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class SimpleMongoRepositoryUnitTests { SimpleMongoRepository repository; @Mock MongoOperations mongoOperations; @Mock MongoEntityInformation entityInformation; - @Before + @BeforeEach public void setUp() { repository = new SimpleMongoRepository<>(entityInformation, mongoOperations); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java index 4d1fdea644..30cca5aff0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java @@ -21,14 +21,12 @@ import static org.springframework.data.mongodb.core.query.Query.*; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -39,12 +37,11 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.VersionedPerson; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.support.TransactionTemplate; import com.mongodb.client.MongoClient; @@ -53,7 +50,7 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) +@ExtendWith(SpringExtension.class) @ContextConfiguration public class SimpleMongoRepositoryVersionedEntityTests { @@ -76,17 +73,14 @@ protected Set> getInitialEntitySet() throws ClassNotFoundException { } } - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); - - @Autowired // - private MongoTemplate template; + @Autowired private MongoTemplate template; private MongoEntityInformation personEntityInformation; private SimpleMongoRepository repository; private VersionedPerson sarah; - @Before + @BeforeEach public void setUp() { MongoPersistentEntity entity = template.getConverter().getMappingContext() @@ -108,7 +102,7 @@ public void deleteWithMatchingVersion() { } @Test // DATAMONGO-2195 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void deleteWithMatchingVersionInTx() { assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); @@ -137,7 +131,7 @@ public void deleteWithVersionMismatch() { } @Test // DATAMONGO-2195 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void deleteWithVersionMismatchInTx() { assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); @@ -164,7 +158,7 @@ public void deleteNonExisting() { } @Test // DATAMONGO-2195 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void deleteNonExistingInTx() { assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java index d283eedeab..b578ee75ad 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java @@ -38,12 +38,12 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.Example; import org.springframework.data.domain.Sort; @@ -55,27 +55,24 @@ /** * @author Christoph Strobl */ -@RunWith(MockitoJUnitRunner.class) -public class SimpleReactiveMongoRepositoryUnitTests { +@ExtendWith(MockitoExtension.class) +class SimpleReactiveMongoRepositoryUnitTests { - SimpleReactiveMongoRepository repository; + private SimpleReactiveMongoRepository repository; @Mock Mono mono; @Mock Flux flux; @Mock ReactiveMongoOperations mongoOperations; @Mock MongoEntityInformation entityInformation; - @Before - public void setUp() { - - when(mongoOperations.count(any(), any(), any())).thenReturn(mono); - when(mongoOperations.exists(any(), any(), any())).thenReturn(mono); - when(mongoOperations.find(any(), any(), any())).thenReturn(flux); - + @BeforeEach + void setUp() { repository = new SimpleReactiveMongoRepository<>(entityInformation, mongoOperations); } @Test // DATAMONGO-1854 - public void shouldAddDefaultCollationToCountForExampleIfPresent() { + void shouldAddDefaultCollationToCountForExampleIfPresent() { + + when(mongoOperations.count(any(), any(), any())).thenReturn(mono); Collation collation = Collation.of("en_US"); @@ -89,7 +86,9 @@ public void shouldAddDefaultCollationToCountForExampleIfPresent() { } @Test // DATAMONGO-1854 - public void shouldAddDefaultCollationToExistsForExampleIfPresent() { + void shouldAddDefaultCollationToExistsForExampleIfPresent() { + + when(mongoOperations.exists(any(), any(), any())).thenReturn(mono); Collation collation = Collation.of("en_US"); @@ -103,7 +102,9 @@ public void shouldAddDefaultCollationToExistsForExampleIfPresent() { } @Test // DATAMONGO-1854 - public void shouldAddDefaultCollationToFindForExampleIfPresent() { + void shouldAddDefaultCollationToFindForExampleIfPresent() { + + when(mongoOperations.find(any(), any(), any())).thenReturn(flux); Collation collation = Collation.of("en_US"); @@ -117,7 +118,9 @@ public void shouldAddDefaultCollationToFindForExampleIfPresent() { } @Test // DATAMONGO-1854 - public void shouldAddDefaultCollationToFindWithSortForExampleIfPresent() { + void shouldAddDefaultCollationToFindWithSortForExampleIfPresent() { + + when(mongoOperations.find(any(), any(), any())).thenReturn(flux); Collation collation = Collation.of("en_US"); @@ -131,7 +134,9 @@ public void shouldAddDefaultCollationToFindWithSortForExampleIfPresent() { } @Test // DATAMONGO-1854 - public void shouldAddDefaultCollationToFindOneForExampleIfPresent() { + void shouldAddDefaultCollationToFindOneForExampleIfPresent() { + + when(mongoOperations.find(any(), any(), any())).thenReturn(flux); Collation collation = Collation.of("en_US"); @@ -144,7 +149,7 @@ public void shouldAddDefaultCollationToFindOneForExampleIfPresent() { assertThat(query.getValue().getCollation()).contains(collation); } - static class TestDummy { + private static class TestDummy { } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java index 23b2405f94..d9cfad319a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java @@ -18,11 +18,11 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import reactor.test.StepVerifier; + import java.util.Collections; import java.util.Set; -import reactor.test.StepVerifier; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java index c8b90ea22a..15eae62aaa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java @@ -24,11 +24,12 @@ import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -57,14 +58,14 @@ * @author Mark Paluch * @author Mikhail Kaduchka */ -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(MockitoExtension.class) public class SpringDataMongodbSerializerUnitTests { @Mock DbRefResolver dbFactory; MongoConverter converter; SpringDataMongodbSerializer serializer; - @Before + @BeforeEach public void setUp() { MongoMappingContext context = new MongoMappingContext(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java index 6060f915ac..2bcb804766 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java @@ -22,13 +22,16 @@ import java.util.Collections; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.runner.Description; -import org.junit.runner.RunWith; import org.junit.runners.model.Statement; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + import org.springframework.data.mongodb.test.util.CleanMongoDB.Struct; import com.mongodb.client.ListDatabasesIterable; @@ -40,8 +43,9 @@ * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(MockitoJUnitRunner.class) -public class CleanMongoDBTests { +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class CleanMongoDBTests { private CleanMongoDB cleaner; @@ -57,8 +61,8 @@ public class CleanMongoDBTests { private @Mock MongoCollection db1collection1mock, db1collection2mock, db2collection1mock; @SuppressWarnings({ "serial", "unchecked" }) - @Before - public void setUp() { + @BeforeEach + void setUp() { // DB setup @@ -86,7 +90,7 @@ public void setUp() { } @Test - public void preservesSystemDBsCorrectlyWhenCleaningDatabase() throws Throwable { + void preservesSystemDBsCorrectlyWhenCleaningDatabase() throws Throwable { cleaner.clean(Struct.DATABASE); @@ -96,7 +100,7 @@ public void preservesSystemDBsCorrectlyWhenCleaningDatabase() throws Throwable { } @Test - public void preservesNamedDBsCorrectlyWhenCleaningDatabase() throws Throwable { + void preservesNamedDBsCorrectlyWhenCleaningDatabase() throws Throwable { cleaner.clean(Struct.DATABASE); cleaner.preserveDatabases("db1"); @@ -107,7 +111,7 @@ public void preservesNamedDBsCorrectlyWhenCleaningDatabase() throws Throwable { } @Test - public void dropsAllDBsCorrectlyWhenCleaingDatabaseAndNotExplictDBNamePresent() throws Throwable { + void dropsAllDBsCorrectlyWhenCleaingDatabaseAndNotExplictDBNamePresent() throws Throwable { cleaner.clean(Struct.DATABASE); @@ -118,7 +122,7 @@ public void dropsAllDBsCorrectlyWhenCleaingDatabaseAndNotExplictDBNamePresent() } @Test - public void dropsSpecifiedDBsCorrectlyWhenExplicitNameSet() throws Throwable { + void dropsSpecifiedDBsCorrectlyWhenExplicitNameSet() throws Throwable { cleaner.clean(Struct.DATABASE); cleaner.useDatabases("db2"); @@ -130,7 +134,7 @@ public void dropsSpecifiedDBsCorrectlyWhenExplicitNameSet() throws Throwable { } @Test - public void doesNotRemoveAnyDBwhenCleaningCollections() throws Throwable { + void doesNotRemoveAnyDBwhenCleaningCollections() throws Throwable { cleaner.clean(Struct.COLLECTION); @@ -142,7 +146,7 @@ public void doesNotRemoveAnyDBwhenCleaningCollections() throws Throwable { } @Test - public void doesNotDropCollectionsFromPreservedDBs() throws Throwable { + void doesNotDropCollectionsFromPreservedDBs() throws Throwable { cleaner.clean(Struct.COLLECTION); cleaner.preserveDatabases("db1"); @@ -155,7 +159,7 @@ public void doesNotDropCollectionsFromPreservedDBs() throws Throwable { } @Test - public void removesAllCollectionsFromAllDatabasesWhenNotLimitedToSpecificOnes() throws Throwable { + void removesAllCollectionsFromAllDatabasesWhenNotLimitedToSpecificOnes() throws Throwable { cleaner.clean(Struct.COLLECTION); @@ -167,7 +171,7 @@ public void removesAllCollectionsFromAllDatabasesWhenNotLimitedToSpecificOnes() } @Test - public void removesOnlyNamedCollectionsWhenSpecified() throws Throwable { + void removesOnlyNamedCollectionsWhenSpecified() throws Throwable { cleaner.clean(Struct.COLLECTION); cleaner.useCollections("db1collection2"); @@ -180,7 +184,7 @@ public void removesOnlyNamedCollectionsWhenSpecified() throws Throwable { } @Test - public void removesIndexesCorrectly() throws Throwable { + void removesIndexesCorrectly() throws Throwable { cleaner.clean(Struct.INDEX); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java index b791fb1b91..9679d837c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java @@ -121,7 +121,7 @@ private SyncClientHolder syncClient(boolean replSet) { return new SyncClientHolder(replSet ? MongoTestUtils.replSetClient() : MongoTestUtils.client()); } - protected boolean holdsReplSetClient(ExtensionContext context) { + boolean holdsReplSetClient(ExtensionContext context) { Store store = context.getStore(NAMESPACE); return store.get(SYNC_REPLSET_KEY) != null || store.get(REACTIVE_REPLSET_KEY) != null; @@ -130,9 +130,6 @@ protected boolean holdsReplSetClient(ExtensionContext context) { private void assertValidFieldCandidate(Field field) { assertSupportedType("field", field.getType()); - if (isPrivate(field)) { - throw new ExtensionConfigurationException("@MongoClient field [" + field + "] must not be private."); - } } private void assertSupportedType(String target, Class type) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java index c88425ba8a..e0ca516c47 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java @@ -15,55 +15,75 @@ */ package org.springframework.data.mongodb.test.util; -import static org.junit.platform.commons.util.AnnotationUtils.*; -import static org.junit.platform.commons.util.ReflectionUtils.*; - import java.lang.reflect.Field; import java.util.List; import java.util.function.Predicate; +import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.mapping.model.CamelCaseSplittingFieldNamingStrategy; + +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.test.util.MongoExtensions.Termplate; import org.springframework.data.util.ParsingUtils; import org.springframework.util.ClassUtils; /** + * JUnit {@link Extension} providing parameter resolution for synchronous and reactive MongoDB Template API objects. + * * @author Christoph Strobl + * @see Template + * @see MongoTestTemplate + * @see ReactiveMongoTestTemplate */ public class MongoTemplateExtension extends MongoClientExtension { - private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplateExtension.class); - CamelCaseSplittingFieldNamingStrategy splitter = new CamelCaseSplittingFieldNamingStrategy("-"); + private static final String DEFAULT_DATABASE = "database"; @Override - public void afterAll(ExtensionContext context) throws Exception { + public void beforeAll(ExtensionContext context) throws Exception { + + super.beforeAll(context); + injectFields(context, null, ReflectionUtils::isStatic); } @Override - public void beforeAll(ExtensionContext context) throws Exception { - super.beforeAll(context); + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return super.supportsParameter(parameterContext, extensionContext) || parameterContext.isAnnotated(Template.class); + } - injectFields(context, null, ReflectionUtils::isStatic); + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + + if (parameterContext.getParameter().getAnnotation(Template.class) == null) { + return super.resolveParameter(parameterContext, extensionContext); + } + + Class parameterType = parameterContext.getParameter().getType(); + return getMongoTemplate(parameterType, parameterContext.getParameter().getAnnotation(Template.class), + extensionContext); } private void injectFields(ExtensionContext context, Object testInstance, Predicate predicate) { - findAnnotatedFields(context.getRequiredTestClass(), Template.class, predicate).forEach(field -> { + AnnotationUtils.findAnnotatedFields(context.getRequiredTestClass(), Template.class, predicate).forEach(field -> { + assertValidFieldCandidate(field); + try { - makeAccessible(field).set(testInstance, + ReflectionUtils.makeAccessible(field).set(testInstance, getMongoTemplate(field.getType(), field.getAnnotation(Template.class), context)); } catch (Throwable t) { ExceptionUtils.throwAsUncheckedException(t); @@ -74,19 +94,15 @@ private void injectFields(ExtensionContext context, Object testInstance, Predica private void assertValidFieldCandidate(Field field) { assertSupportedType("field", field.getType()); - if (isPrivate(field)) { - throw new ExtensionConfigurationException("@MongoClient field [" + field + "] must not be private."); - } } private void assertSupportedType(String target, Class type) { - if (!ClassUtils.isAssignable(org.springframework.data.mongodb.core.MongoOperations.class, type) - && !ClassUtils.isAssignable(org.springframework.data.mongodb.core.ReactiveMongoOperations.class, type)) { - throw new ExtensionConfigurationException("Can only resolve @MongoClient " + target + " of type " - + org.springframework.data.mongodb.core.MongoOperations.class.getName() + " or " - + org.springframework.data.mongodb.core.ReactiveMongoOperations.class.getName() + " but was: " - + type.getName()); + if (!ClassUtils.isAssignable(MongoOperations.class, type) + && !ClassUtils.isAssignable(ReactiveMongoOperations.class, type)) { + throw new ExtensionConfigurationException( + String.format("Can only resolve @%s %s of type %s or %s but was: %s", Template.class.getSimpleName(), target, + MongoOperations.class.getName(), ReactiveMongoOperations.class.getName(), type.getName())); } } @@ -100,9 +116,9 @@ private Object getMongoTemplate(Class type, Template options, ExtensionContex : extensionContext.getTestClass().map(it -> { List target = ParsingUtils.splitCamelCaseToLower(it.getSimpleName()); return org.springframework.util.StringUtils.collectionToDelimitedString(target, "-"); - }).orElse("database"); + }).orElse(DEFAULT_DATABASE); - if (ClassUtils.isAssignable(org.springframework.data.mongodb.core.MongoOperations.class, type)) { + if (ClassUtils.isAssignable(MongoOperations.class, type)) { String key = Termplate.SYNC + "-" + dbName; return templateStore.getOrComputeIfAbsent(key, it -> { @@ -113,7 +129,7 @@ private Object getMongoTemplate(Class type, Template options, ExtensionContex }); } - if (ClassUtils.isAssignable(org.springframework.data.mongodb.core.ReactiveMongoOperations.class, type)) { + if (ClassUtils.isAssignable(ReactiveMongoOperations.class, type)) { String key = Termplate.REACTIVE + "-" + dbName; return templateStore.getOrComputeIfAbsent(key, it -> { @@ -126,22 +142,4 @@ private Object getMongoTemplate(Class type, Template options, ExtensionContex throw new IllegalStateException("Damn - something went wrong."); } - - @Override - public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) - throws ParameterResolutionException { - return super.supportsParameter(parameterContext, extensionContext) || parameterContext.isAnnotated(Template.class); - } - - @Override - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) - throws ParameterResolutionException { - - if (parameterContext.getParameter().getAnnotation(Template.class) == null) { - return super.resolveParameter(parameterContext, extensionContext); - } - Class parameterType = parameterContext.getParameter().getType(); - return getMongoTemplate(parameterType, parameterContext.getParameter().getAnnotation(Template.class), - extensionContext); - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java index 66762b533f..290b78c2d5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.test.util; -import com.mongodb.reactivestreams.client.MongoClient; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -25,14 +24,17 @@ import org.bson.Document; import org.reactivestreams.Publisher; + import org.springframework.context.ApplicationContext; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import com.mongodb.reactivestreams.client.MongoClient; + /** * A {@link ReactiveMongoTemplate} with configuration hooks and extension suitable for tests. - * + * * @author Christoph Strobl * @since 3.0 */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java index 89e8f02278..13ccb04313 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java @@ -25,8 +25,13 @@ import org.junit.jupiter.api.extension.ExtensionContext; /** + * Annotation to inject {@link org.springframework.data.mongodb.core.MongoOperations} and + * {@link org.springframework.data.mongodb.core.ReactiveMongoOperations} parameters as method arguments and into + * {@code static} fields. + * * @author Christoph Strobl * @since 3.0 + * @see MongoTemplateExtension */ @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @@ -41,15 +46,15 @@ String database() default ""; /** - * Pre initilaize the {@link org.springframework.data.mapping.context.MappingContext} with the given entities. - * + * Pre-initialize the {@link org.springframework.data.mapping.context.MappingContext} with the given entities. + * * @return empty by default. */ Class[] initialEntitySet() default {}; /** * Use a {@link ReplSetClient} if {@literal true}. - * + * * @return false by default. */ boolean replicaSet() default false; From 7e3f7bd86137b0d9bd1d4cb3c09ba19bb7674723 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 6 Mar 2020 11:34:13 +0100 Subject: [PATCH 0094/1381] DATAMONGO-2481 - Polishing. Add since tag. Original pull request: #838. --- .../data/mongodb/core/messaging/ChangeStreamRequest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java index c4ed0687cb..bc104fe327 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java @@ -190,6 +190,7 @@ public ChangeStreamRequestOptions(@Nullable String databaseName, @Nullable Strin * @param collectionName can be {@literal null}. * @param maxAwaitTime can be {@literal null}. * @param options must not be {@literal null}. + * @since 3.0 */ public ChangeStreamRequestOptions(@Nullable String databaseName, @Nullable String collectionName, @Nullable Duration maxAwaitTime, ChangeStreamOptions options) { @@ -260,7 +261,7 @@ public static class ChangeStreamRequestBuilder { private @Nullable String collectionName; private @Nullable Duration maxAwaitTime; private @Nullable MessageListener, ? super T> listener; - private ChangeStreamOptionsBuilder delegate = ChangeStreamOptions.builder(); + private final ChangeStreamOptionsBuilder delegate = ChangeStreamOptions.builder(); private ChangeStreamRequestBuilder() {} @@ -357,7 +358,7 @@ public ChangeStreamRequestBuilder filter(Document... pipeline) { * @see ChangeStreamOptions#getCollation() * @see ChangeStreamOptionsBuilder#collation(Collation) */ - public ChangeStreamRequestBuilder collation(Collation collation) { + public ChangeStreamRequestBuilder collation(Collation collation) { Assert.notNull(collation, "Collation must not be null!"); From a4e12a96c9d3dc7ac2707e35a9dcc391999d00ef Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 28 Oct 2019 15:04:30 +0100 Subject: [PATCH 0095/1381] DATAMONGO-2363 - Add support for $merge and $addFields aggregation stage. MergeOperation.builder().intoCollection("monthlytotals") .whenDocumentsMatchApply( newAggregation( AddFieldsOperation.builder() .addField("thumbsup").withValueOf(sumOf("thumbsup").and("$$new.thumbsup")) .addField("thumbsdown").withValueOf(sumOf("thumbsdown").and("$$new.thumbsdown")) .build() ) ) .whenDocumentsDontMatch(insertNewDocument()) .build() Original pull request: #801. --- .../core/aggregation/AddFieldsOperation.java | 185 ++++++ .../mongodb/core/aggregation/Aggregation.java | 24 + .../AggregationOperationContext.java | 13 +- .../DocumentEnhancingOperation.java | 125 ++++ .../core/aggregation/MergeOperation.java | 583 ++++++++++++++++++ .../core/aggregation/SetOperation.java | 86 +-- .../TypeBasedAggregationOperationContext.java | 9 + .../core/aggregation/VariableOperators.java | 2 +- .../AddFieldsOperationUnitTests.java | 146 +++++ .../aggregation/MergeOperationUnitTests.java | 126 ++++ src/main/asciidoc/new-features.adoc | 1 + 11 files changed, 1218 insertions(+), 82 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java new file mode 100644 index 0000000000..984cfdc8ca --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java @@ -0,0 +1,185 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.springframework.data.mongodb.core.aggregation.AddFieldsOperation.AddFieldsOperationBuilder.ValueAppender; +import org.springframework.lang.Nullable; + +/** + * Adds new fields to documents. {@code $addFields} outputs documents that contain all existing fields from the input + * documents and newly added fields. + * + *
      + * AddFieldsOperation.addField("totalHomework").withValue("A+").and().addField("totalQuiz").withValue("B-")
      + * 
      + * + * @author Christoph Strobl + * @since 3.0 + * @see MongoDB Aggregation + * Framework: $addFields + */ +public class AddFieldsOperation extends DocumentEnhancingOperation { + + /** + * Create new instance of {@link AddFieldsOperation} adding map keys as exposed fields. + * + * @param source must not be {@literal null}. + */ + private AddFieldsOperation(Map source) { + super(source); + } + + /** + * Create new instance of {@link AddFieldsOperation} + * + * @param field must not be {@literal null}. + * @param value can be {@literal null}. + */ + public AddFieldsOperation(Object field, @Nullable Object value) { + this(Collections.singletonMap(field, value)); + } + + /** + * Define the {@link AddFieldsOperation} via {@link AddFieldsOperationBuilder}. + * + * @return new instance of {@link AddFieldsOperationBuilder}. + */ + public static AddFieldsOperationBuilder builder() { + return new AddFieldsOperationBuilder(); + } + + /** + * Concatenate another field to add. + * + * @param field must not be {@literal null}. + * @return new instance of {@link AddFieldsOperationBuilder}. + */ + public static ValueAppender addField(String field) { + return new AddFieldsOperationBuilder().addField(field); + } + + /** + * Append the value for a specific field to the operation. + * + * @param field the target field to add. + * @param value the value to assign. + * @return new instance of {@link AddFieldsOperation}. + */ + public AddFieldsOperation addField(Object field, Object value) { + + LinkedHashMap target = new LinkedHashMap<>(getValueMap()); + target.put(field, value); + + return new AddFieldsOperation(target); + } + + /** + * Concatenate additional fields to add. + * + * @return new instance of {@link AddFieldsOperationBuilder}. + */ + public AddFieldsOperationBuilder and() { + return new AddFieldsOperationBuilder(getValueMap()); + } + + @Override + protected String mongoOperator() { + return "$addFields"; + } + + /** + * @author Christoph Strobl + * @since 3.0 + */ + public static class AddFieldsOperationBuilder { + + private final Map valueMap; + + private AddFieldsOperationBuilder() { + this.valueMap = new LinkedHashMap<>(); + } + + private AddFieldsOperationBuilder(Map source) { + this.valueMap = new LinkedHashMap<>(source); + } + + public AddFieldsOperationBuilder addFieldWithValue(String field, @Nullable Object value) { + return addField(field).withValue(value); + } + + public AddFieldsOperationBuilder addFieldWithValueOf(String field, Object value) { + return addField(field).withValueOf(value); + } + + /** + * Define the field to add. + * + * @param field must not be {@literal null}. + * @return new instance of {@link ValueAppender}. + */ + public ValueAppender addField(String field) { + + return new ValueAppender() { + + @Override + public AddFieldsOperationBuilder withValue(Object value) { + + valueMap.put(field, value); + return AddFieldsOperationBuilder.this; + } + + @Override + public AddFieldsOperationBuilder withValueOf(Object value) { + + valueMap.put(field, value instanceof String ? Fields.fields((String) value) : value); + return AddFieldsOperationBuilder.this; + } + }; + } + + public AddFieldsOperation build() { + return new AddFieldsOperation(valueMap); + } + + /** + * @author Christoph Strobl + * @since 3.0 + */ + public interface ValueAppender { + + /** + * Define the value to assign as is. + * + * @param value can be {@literal null}. + * @return new instance of {@link AddFieldsOperation}. + */ + AddFieldsOperationBuilder withValue(@Nullable Object value); + + /** + * Define the value to assign. Plain {@link String} values are treated as {@link Field field references}. + * + * @param value must not be {@literal null}. + * @return new instance of {@link AddFieldsOperation}. + */ + AddFieldsOperationBuilder withValueOf(Object value); + } + + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index c7e8c1b2cb..44376d6e83 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -23,9 +23,11 @@ import org.bson.Document; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.mongodb.core.aggregation.AddFieldsOperation.AddFieldsOperationBuilder; import org.springframework.data.mongodb.core.aggregation.CountOperation.CountOperationBuilder; import org.springframework.data.mongodb.core.aggregation.FacetOperation.FacetOperationBuilder; import org.springframework.data.mongodb.core.aggregation.GraphLookupOperation.StartWithBuilder; +import org.springframework.data.mongodb.core.aggregation.MergeOperation.MergeOperationBuilder; import org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplaceRootDocumentOperationBuilder; import org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplaceRootOperationBuilder; import org.springframework.data.mongodb.core.query.Criteria; @@ -647,6 +649,28 @@ public static GeoNearOperation geoNear(NearQuery query, String distanceField) { return new GeoNearOperation(query, distanceField); } + /** + * Obtain a {@link MergeOperationBuilder builder} instance to create a new {@link MergeOperation}. + * + * @return new instance of {@link MergeOperationBuilder}. + * @see MergeOperation + * @since 3.0 + */ + public static MergeOperationBuilder merge() { + return MergeOperation.builder(); + } + + /** + * Obtain an {@link AddFieldsOperationBuilder builder} instance to create a new {@link AddFieldsOperation}. + * + * @return new instance of {@link AddFieldsOperationBuilder}. + * @see AddFieldsOperation + * @since 3.0 + */ + public static AddFieldsOperationBuilder addFields() { + return AddFieldsOperation.builder(); + } + /** * Returns a new {@link AggregationOptions.Builder}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java index 56940180ad..6862cf5156 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java @@ -20,7 +20,6 @@ import java.util.Arrays; import org.bson.Document; - import org.springframework.beans.BeanUtils; import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference; import org.springframework.lang.Nullable; @@ -103,4 +102,16 @@ default Fields getFields(Class type) { .map(PropertyDescriptor::getName) // .toArray(String[]::new)); } + + /** + * This toggle allows the {@link AggregationOperationContext context} to use any given field name without checking for + * its existence. Typically the {@link AggregationOperationContext} fails when referencing unknown fields, those that + * are not present in one of the previous stages or the input source, throughout the pipeline. + * + * @return a more relaxed {@link AggregationOperationContext}. + * @since 3.0 + */ + default AggregationOperationContext continueOnMissingFieldReference() { + return this; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java new file mode 100644 index 0000000000..9c078de59b --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java @@ -0,0 +1,125 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.bson.Document; +import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; +import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation; + +/** + * Base class for common taks required by {@link SetOperation} and {@link AddFieldsOperation}. + * + * @author Christoph Strobl + * @since 3.0 + */ +abstract class DocumentEnhancingOperation implements InheritsFieldsAggregationOperation { + + private Map valueMap; + private ExposedFields exposedFields = ExposedFields.empty(); + + protected DocumentEnhancingOperation(Map source) { + + this.valueMap = new LinkedHashMap<>(source); + for (Object key : source.keySet()) { + this.exposedFields = add(key); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) + */ + @Override + public Document toDocument(AggregationOperationContext context) { + + InheritingExposedFieldsAggregationOperationContext operationContext = new InheritingExposedFieldsAggregationOperationContext( + exposedFields, context); + + if (valueMap.size() == 1) { + return context.getMappedObject( + new Document(mongoOperator(), toSetEntry(valueMap.entrySet().iterator().next(), operationContext))); + } + + Document $set = new Document(); + valueMap.entrySet().stream().map(it -> toSetEntry(it, operationContext)).forEach($set::putAll); + return context.getMappedObject(new Document(mongoOperator(), $set)); + } + + /** + * @return the String representation of the native MongoDB operator. + */ + protected abstract String mongoOperator(); + + /** + * @return the raw value map + */ + protected Map getValueMap() { + return this.valueMap; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields() + */ + @Override + public ExposedFields getFields() { + return exposedFields; + } + + private ExposedFields add(Object field) { + + if (field instanceof Field) { + return exposedFields.and(new ExposedField((Field) field, true)); + } + if (field instanceof String) { + return exposedFields.and(new ExposedField(Fields.field((String) field), true)); + } + + throw new IllegalArgumentException(String.format("Expected %s to be a field/property.", field)); + } + + private static Document toSetEntry(Entry entry, AggregationOperationContext context) { + + String field = entry.getKey() instanceof String ? context.getReference((String) entry.getKey()).getRaw() + : context.getReference((Field) entry.getKey()).getRaw(); + + Object value = computeValue(entry.getValue(), context); + + return new Document(field, value); + } + + private static Object computeValue(Object value, AggregationOperationContext context) { + + if (value instanceof Field) { + return context.getReference((Field) value).toString(); + } + if (value instanceof AggregationExpression) { + return ((AggregationExpression) value).toDocument(context); + } + if (value instanceof Collection) { + return ((Collection) value).stream().map(it -> computeValue(it, context)).collect(Collectors.toList()); + } + + return value; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java new file mode 100644 index 0000000000..188f9d72db --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java @@ -0,0 +1,583 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.bson.Document; +import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference; +import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation; +import org.springframework.data.mongodb.core.aggregation.VariableOperators.Let; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +/** + * Encapsulates the {@code $merge}-operation. + *

      + * We recommend to use the {@link MergeOperationBuilder builder} via {@link MergeOperation#builder()} instead of creating + * instances of this class directly. + * + * @see MongoDB Documentation + * @author Christoph Strobl + * @since 3.0 + */ +public class MergeOperation implements FieldsExposingAggregationOperation, InheritsFieldsAggregationOperation { + + private MergeOperationTarget into; + private UniqueMergeId on; + private @Nullable Let let; + private @Nullable WhenDocumentsMatch whenMatched; + private @Nullable WhenDocumentsDontMatch whenNotMatched; + + /** + * Create new instance of {@link MergeOperation}. + * + * @param into the target (collection and database) + * @param on the unique identifier. Can be {@literal null}. + * @param let exposed variables for {@link WhenDocumentsMatch#updateWith(Aggregation)}. Can be {@literal null}. + * @param whenMatched behavior if a result document matches an existing one in the target collection. Can be + * {@literal null}. + * @param whenNotMatched behavior if a result document does not match an existing one in the target collection. Can be + * {@literal null}. + */ + public MergeOperation(MergeOperationTarget into, UniqueMergeId on, @Nullable Let let, + @Nullable WhenDocumentsMatch whenMatched, @Nullable WhenDocumentsDontMatch whenNotMatched) { + + Assert.notNull(into, "Into must not be null! Please provide a target collection."); + Assert.notNull(on, "On must not be null! Use Collections.emptySet() instead."); + + this.into = into; + this.on = on; + this.let = let; + this.whenMatched = whenMatched; + this.whenNotMatched = whenNotMatched; + } + + /** + * Simplified form to apply all default options for {@code $merge} (including writing to a collection in the same + * database). + * + * @param collection the output collection within the same database. + * @return new instance of {@link MergeOperation}. + */ + public static MergeOperation mergeInto(String collection) { + return builder().intoCollection(collection).build(); + } + + /** + * Access the {@link MergeOperationBuilder builder API} to create a new instance of {@link MergeOperation}. + * + * @return new instance of {@link MergeOperationBuilder}. + */ + public static MergeOperationBuilder builder() { + return new MergeOperationBuilder(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.Aggregation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) + */ + @Override + public Document toDocument(AggregationOperationContext context) { + + if (isJustCollection()) { + return new Document("$merge", into.collection); + } + + Document $merge = new Document(); + $merge.putAll(into.toDocument(context)); + + if (!on.isJustIdField()) { + $merge.putAll(on.toDocument(context)); + } + if (let != null) { + $merge.append("let", let.toDocument(context).get("$let", Document.class).get("vars")); + } + if (whenMatched != null) { + $merge.putAll(whenMatched.toDocument(context)); + } + if (whenNotMatched != null) { + $merge.putAll(whenNotMatched.toDocument(context)); + + } + + return new Document("$merge", $merge); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields() + */ + @Override + public ExposedFields getFields() { + + if (let == null) { + return ExposedFields.from(); + } + + return ExposedFields.synthetic(Fields.fields(let.getVariableNames())); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation#inheritsFields() + */ + @Override + public boolean inheritsFields() { + return true; + } + + /** + * @return true if nothing more than the collection is specified. + */ + private boolean isJustCollection() { + return into.isTargetingSameDatabase() && on.isJustIdField() && let == null && whenMatched == null + && whenNotMatched == null; + } + + /** + * Value object representing the unique id used during the merge operation to identify duplicates in the target + * collection. + * + * @author Christoph Strobl + * @since 2.3 + */ + public static class UniqueMergeId { + + private static final UniqueMergeId ID = new UniqueMergeId(Collections.emptyList()); + + private Collection uniqueIdentifier; + + private UniqueMergeId(Collection uniqueIdentifier) { + this.uniqueIdentifier = uniqueIdentifier; + } + + public static UniqueMergeId ofIdFields(String... fields) { + + if (ObjectUtils.isEmpty(fields)) { + return id(); + } + + return new UniqueMergeId(Arrays.asList(fields)); + } + + /** + * Merge Documents by using the MongoDB {@literal _id} field. + * + * @return + */ + public static UniqueMergeId id() { + return ID; + } + + boolean isJustIdField() { + return this.equals(ID); + } + + Document toDocument(AggregationOperationContext context) { + + List mappedOn = uniqueIdentifier.stream().map(context::getReference).map(FieldReference::getRaw) + .collect(Collectors.toList()); + return new Document("on", mappedOn.size() == 1 ? mappedOn.iterator().next() : mappedOn); + } + } + + /** + * Value Object representing the {@code into} field of a {@code $merge} aggregation stage.
      + * If not stated explicitly via {@link MergeOperationTarget#inDatabase(String)} the {@literal collection} is created + * in the very same {@literal database}. In this case {@code into} is just a single String holding the collection + * name.
      + * + *

      +	 *     into: "target-collection-name"
      +	 * 
      + * + * If the collection needs to be in a different database {@code into} will be a {@link Document} like the following + * + *
      +	 * {
      +	 * 	into: {}
      +	 * }
      +	 * 
      + * + * @author Christoph Strobl + * @since 2.3 + */ + public static class MergeOperationTarget { + + private final @Nullable String database; + private final String collection; + + private MergeOperationTarget(@Nullable String database, String collection) { + + Assert.hasText(collection, "Collection must not be null nor empty!"); + + this.database = database; + this.collection = collection; + } + + /** + * @param collection The output collection results will be stored in. Must not be {@literal null}. + * @return new instance of {@link MergeOperationTarget}. + */ + public static MergeOperationTarget collection(String collection) { + return new MergeOperationTarget(null, collection); + } + + /** + * Optionally specify the target database if different from the source one. + * + * @param database must not be {@literal null}. + * @return new instance of {@link MergeOperationTarget}. + */ + public MergeOperationTarget inDatabase(String database) { + return new MergeOperationTarget(database, collection); + } + + boolean isTargetingSameDatabase() { + return !StringUtils.hasText(database); + } + + Document toDocument(AggregationOperationContext context) { + + return new Document("into", + !StringUtils.hasText(database) ? collection : new Document("db", database).append("coll", collection)); + } + } + + /** + * Value Object specifying how to deal with a result document that matches an existing document in the collection + * based on the fields of the {@code on} property describing the unique identifier. + * + * @author Christoph Strobl + * @since 2.3 + */ + public static class WhenDocumentsMatch { + + private final Object value; + + private WhenDocumentsMatch(Object value) { + this.value = value; + } + + public static WhenDocumentsMatch whenMatchedOf(String value) { + return new WhenDocumentsMatch(value); + } + + /** + * Replace the existing document in the output collection with the matching results document. + * + * @return new instance of {@link WhenDocumentsMatch}. + */ + public static WhenDocumentsMatch replaceDocument() { + return whenMatchedOf("replace"); + } + + /** + * Keep the existing document in the output collection. + * + * @return new instance of {@link WhenDocumentsMatch}. + */ + public static WhenDocumentsMatch keepExistingDocument() { + return whenMatchedOf("keepExisting"); + } + + /** + * Merge the matching documents. Please see the MongoDB reference documentation for details. + * + * @return new instance of {@link WhenDocumentsMatch}. + */ + public static WhenDocumentsMatch mergeDocuments() { + return whenMatchedOf("merge"); + } + + /** + * Stop and fail the aggregation operation. Does not revert already performed changes on previous documents. + * + * @return new instance of {@link WhenDocumentsMatch}. + */ + public static WhenDocumentsMatch failOnMatch() { + return whenMatchedOf("fail"); + } + + /** + * Use an {@link Aggregation} to update the document in the collection. Please see the MongoDB reference + * documentation for details. + * + * @param aggregation must not be {@literal null}. + * @return new instance of {@link WhenDocumentsMatch}. + */ + public static WhenDocumentsMatch updateWith(Aggregation aggregation) { + return new WhenDocumentsMatch(aggregation); + } + + /** + * Use an aggregation pipeline to update the document in the collection. Please see the MongoDB reference + * documentation for details. + * + * @param aggregationPipeline must not be {@literal null}. + * @return new instance of {@link WhenDocumentsMatch}. + */ + public static WhenDocumentsMatch updateWith(List aggregationPipeline) { + return new WhenDocumentsMatch(aggregationPipeline); + } + + Document toDocument(AggregationOperationContext context) { + + if (value instanceof Aggregation) { + return new Document("whenMatched", ((Aggregation) value).toPipeline(context)); + } + + return new Document("whenMatched", value); + } + } + + /** + * Value Object specifying how to deal with a result document that do not match an existing document in the collection + * based on the fields of the {@code on} property describing the unique identifier. + * + * @author Christoph Strobl + * @since 2.3 + */ + public static class WhenDocumentsDontMatch { + + private final String value; + + private WhenDocumentsDontMatch(String value) { + this.value = value; + } + + public static WhenDocumentsDontMatch whenNotMatchedOf(String value) { + return new WhenDocumentsDontMatch(value); + } + + /** + * Insert the document into the output collection. + * + * @return new instance of {@link WhenDocumentsDontMatch}. + */ + public static WhenDocumentsDontMatch insertNewDocument() { + return whenNotMatchedOf("insert"); + } + + /** + * Discard the document - do not insert the document into the output collection. + * + * @return new instance of {@link WhenDocumentsDontMatch}. + */ + public static WhenDocumentsDontMatch discardDocument() { + return whenNotMatchedOf("discard"); + } + + /** + * Stop and fail the aggregation operation. Does not revert already performed changes on previous documents. + * + * @return + */ + public static WhenDocumentsDontMatch failWhenNotMatch() { + return whenNotMatchedOf("fail"); + } + + public Document toDocument(AggregationOperationContext context) { + return new Document("whenNotMatched", value); + } + } + + /** + * Builder API to construct a {@link MergeOperation}. + * + * @author Christoph Strobl + * @since 2.3 + */ + public static class MergeOperationBuilder { + + private String collection; + private @Nullable String database; + private @Nullable UniqueMergeId id; + private @Nullable Let let; + private @Nullable WhenDocumentsMatch whenMatched; + private @Nullable WhenDocumentsDontMatch whenNotMatched; + + public MergeOperationBuilder() {} + + /** + * Required output collection name to store results to. + * + * @param collection must not be {@literal null} nor empty. + * @return this. + */ + public MergeOperationBuilder intoCollection(String collection) { + + Assert.hasText(collection, "Collection must not be null nor empty!"); + + this.collection = collection; + return this; + } + + /** + * Optionally define a target database if different from the current one. + * + * @param database must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder inDatabase(String database) { + + this.database = database; + return this; + } + + /** + * Define the target to store results in. + * + * @param into must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder into(MergeOperationTarget into) { + + this.database = into.database; + this.collection = into.collection; + return this; + } + + /** + * Define the target to store results in. + * + * @param target must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder target(MergeOperationTarget target) { + return into(target); + } + + /** + * Appends a single field or multiple fields that act as a unique identifier for a document. The identifier + * determines if a results document matches an already existing document in the output collection.
      + * The aggregation results documents must contain the field(s) specified via {@code on}, unless it's the {@code _id} + * field. + * + * @param fields must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder on(String... fields) { + return id(UniqueMergeId.ofIdFields(fields)); + } + + /** + * Set the identifier that determines if a results document matches an already existing document in the output + * collection. + * + * @param id must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder id(UniqueMergeId id) { + + this.id = id; + return this; + } + + /** + * Expose the variables defined by {@link Let} to the {@link WhenDocumentsMatch#updateWith(Aggregation) update + * aggregation}. + * + * @param let the variable expressions + * @return this. + */ + public MergeOperationBuilder let(Let let) { + + this.let = let; + return this; + } + + /** + * Expose the variables defined by {@link Let} to the {@link WhenDocumentsMatch#updateWith(Aggregation) update + * aggregation}. + * + * @param let the variable expressions + * @return this. + */ + public MergeOperationBuilder exposeVariablesOf(Let let) { + return let(let); + } + + /** + * The action to take place when documents already exist in the target collection. + * + * @param whenMatched must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder whenMatched(WhenDocumentsMatch whenMatched) { + + this.whenMatched = whenMatched; + return this; + } + + /** + * The action to take place when documents already exist in the target collection. + * + * @param whenMatched must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder whenDocumentsMatch(WhenDocumentsMatch whenMatched) { + return whenMatched(whenMatched); + } + + /** + * The {@link Aggregation action} to take place when documents already exist in the target collection. + * + * @param aggregation must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder whenDocumentsMatchApply(Aggregation aggregation) { + return whenMatched(WhenDocumentsMatch.updateWith(aggregation)); + } + + /** + * The action to take place when documents do not already exist in the target collection. + * + * @param whenNotMatched must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder whenNotMatched(WhenDocumentsDontMatch whenNotMatched) { + + this.whenNotMatched = whenNotMatched; + return this; + } + + /** + * The action to take place when documents do not already exist in the target collection. + * + * @param whenNotMatched must not be {@literal null}. + * @return this. + */ + public MergeOperationBuilder whenDocumentsDontMatch(WhenDocumentsDontMatch whenNotMatched) { + return whenNotMatched(whenNotMatched); + } + + /** + * @return new instance of {@link MergeOperation}. + */ + public MergeOperation build() { + return new MergeOperation(new MergeOperationTarget(database, collection), id != null ? id : UniqueMergeId.id(), + let, whenMatched, whenNotMatched); + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index d7b97297ef..5516ece3d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -15,16 +15,10 @@ */ package org.springframework.data.mongodb.core.aggregation; -import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import org.bson.Document; -import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; -import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation; import org.springframework.data.mongodb.core.aggregation.SetOperation.FieldAppender.ValueAppender; import org.springframework.lang.Nullable; @@ -41,10 +35,7 @@ * @see MongoDB Aggregation Framework: * $set */ -public class SetOperation implements InheritsFieldsAggregationOperation { - - private Map valueMap; - private ExposedFields exposedFields = ExposedFields.empty(); +public class SetOperation extends DocumentEnhancingOperation { /** * Create new instance of {@link SetOperation} adding map keys as exposed fields. @@ -52,11 +43,7 @@ public class SetOperation implements InheritsFieldsAggregationOperation { * @param source must not be {@literal null}. */ private SetOperation(Map source) { - - this.valueMap = new LinkedHashMap<>(source); - for (Object key : source.keySet()) { - this.exposedFields = add(key); - } + super(source); } /** @@ -97,7 +84,7 @@ public static ValueAppender set(String field) { */ public SetOperation set(Object field, Object value) { - LinkedHashMap target = new LinkedHashMap<>(this.valueMap); + LinkedHashMap target = new LinkedHashMap<>(getValueMap()); target.put(field, value); return new SetOperation(target); @@ -109,73 +96,12 @@ public SetOperation set(Object field, Object value) { * @return new instance of {@link FieldAppender}. */ public FieldAppender and() { - return new FieldAppender(this.valueMap); + return new FieldAppender(getValueMap()); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) - */ @Override - public Document toDocument(AggregationOperationContext context) { - - InheritingExposedFieldsAggregationOperationContext operationContext = new InheritingExposedFieldsAggregationOperationContext( - exposedFields, context); - - if (valueMap.size() == 1) { - return context - .getMappedObject(new Document("$set", toSetEntry(valueMap.entrySet().iterator().next(), operationContext))); - } - - Document $set = new Document(); - valueMap.entrySet().stream().map(it -> toSetEntry(it, operationContext)).forEach($set::putAll); - return context.getMappedObject(new Document("$set", $set)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields() - */ - @Override - public ExposedFields getFields() { - return exposedFields; - } - - private ExposedFields add(Object field) { - - if (field instanceof Field) { - return exposedFields.and(new ExposedField((Field) field, true)); - } - if (field instanceof String) { - return exposedFields.and(new ExposedField(Fields.field((String) field), true)); - } - - throw new IllegalArgumentException(String.format("Expected %s to be a field/property.", field)); - } - - private static Document toSetEntry(Entry entry, AggregationOperationContext context) { - - String field = entry.getKey() instanceof String ? context.getReference((String) entry.getKey()).getRaw() - : context.getReference((Field) entry.getKey()).getRaw(); - - Object value = computeValue(entry.getValue(), context); - - return new Document(field, value); - } - - private static Object computeValue(Object value, AggregationOperationContext context) { - - if (value instanceof Field) { - return context.getReference((Field) value).toString(); - } - if (value instanceof AggregationExpression) { - return ((AggregationExpression) value).toDocument(context); - } - if (value instanceof Collection) { - return ((Collection) value).stream().map(it -> computeValue(it, context)).collect(Collectors.toList()); - } - - return value; + protected String mongoOperator() { + return "$set"; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java index 59a5eddcf9..5ba22e9603 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java @@ -127,6 +127,15 @@ public Fields getFields(Class type) { return Fields.fields(fields.toArray(new String[0])); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#continueOnMissingFieldReference() + */ + @Override + public AggregationOperationContext continueOnMissingFieldReference() { + return new RelaxedTypeBasedAggregationOperationContext(type, mappingContext, mapper); + } + protected FieldReference getReferenceFor(Field field) { PersistentPropertyPath propertyPath = mappingContext diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java index 4daef44e6b..a89ba122f3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java @@ -296,7 +296,7 @@ public Document toDocument(final AggregationOperationContext context) { return toLet(ExposedFields.synthetic(Fields.fields(getVariableNames())), context); } - private String[] getVariableNames() { + String[] getVariableNames() { String[] varNames = new String[this.vars.size()]; for (int i = 0; i < this.vars.size(); i++) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java new file mode 100644 index 0000000000..829a1ba8a7 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java @@ -0,0 +1,146 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import java.util.List; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + */ +class AddFieldsOperationUnitTests { + + @Test // DATAMONGO-2363 + void raisesErrorOnNullField() { + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new AddFieldsOperation(null, "value")); + } + + @Test // DATAMONGO-2363 + void rendersFieldReferenceCorrectly() { + + assertThat(new AddFieldsOperation("name", "value").toPipelineStages(contextFor(Scores.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"name\":\"value\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersMultipleEntriesCorrectly() { + + assertThat(new AddFieldsOperation("name", "value").addField("field-2", "value2") + .toPipelineStages(contextFor(Scores.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"name\":\"value\", \"field-2\":\"value2\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersMappedFieldReferenceCorrectly() { + + assertThat(new AddFieldsOperation("student", "value").toPipelineStages(contextFor(ScoresWithMappedField.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"student_name\":\"value\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersNestedMappedFieldReferenceCorrectly() { + + assertThat(new AddFieldsOperation("scoresWithMappedField.student", "value") + .toPipelineStages(contextFor(ScoresWrapper.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"scoresWithMappedField.student_name\":\"value\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersTargetValueFieldReferenceCorrectly() { + + assertThat(new AddFieldsOperation("name", Fields.field("value")).toPipelineStages(contextFor(Scores.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"name\":\"$value\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersMappedTargetValueFieldReferenceCorrectly() { + + assertThat(new AddFieldsOperation("student", Fields.field("homework")) + .toPipelineStages(contextFor(ScoresWithMappedField.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"student_name\":\"$home_work\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersNestedMappedTargetValueFieldReferenceCorrectly() { + + assertThat(new AddFieldsOperation("scoresWithMappedField.student", Fields.field("scoresWithMappedField.homework")) + .toPipelineStages(contextFor(ScoresWrapper.class))) + .containsExactly(Document.parse( + "{\"$addFields\" : {\"scoresWithMappedField.student_name\":\"$scoresWithMappedField.home_work\"}}")); + } + + @Test // DATAMONGO-2363 + void rendersTargetValueExpressionCorrectly() { + + assertThat(AddFieldsOperation.builder().addField("totalHomework") + .withValueOf(ArithmeticOperators.valueOf("homework").sum()).build().toPipelineStages(contextFor(Scores.class))) + .containsExactly(Document.parse("{\"$addFields\" : {\"totalHomework\": { \"$sum\" : \"$homework\" }}}")); + } + + @Test // DATAMONGO-2363 + void exposesFieldsCorrectly() { + + ExposedFields fields = AddFieldsOperation.builder().addField("totalHomework").withValue("A+") // + .addField("totalQuiz").withValue("B-") // + .build().getFields(); + + assertThat(fields.getField("totalHomework")).isNotNull(); + assertThat(fields.getField("totalQuiz")).isNotNull(); + assertThat(fields.getField("does-not-exist")).isNull(); + } + + private static AggregationOperationContext contextFor(@Nullable Class type) { + + if (type == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + MappingMongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, + new MongoMappingContext()); + mongoConverter.afterPropertiesSet(); + + return new TypeBasedAggregationOperationContext(type, mongoConverter.getMappingContext(), + new QueryMapper(mongoConverter)).continueOnMissingFieldReference(); + } + + static class Scores { + + String student; + List homework; + } + + static class ScoresWithMappedField { + + @Field("student_name") String student; + @Field("home_work") List homework; + } + + static class ScoresWrapper { + + Scores scores; + ScoresWithMappedField scoresWithMappedField; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java new file mode 100644 index 0000000000..509dfc48dd --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java @@ -0,0 +1,126 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; +import static org.springframework.data.mongodb.core.aggregation.MergeOperation.*; +import static org.springframework.data.mongodb.core.aggregation.MergeOperation.WhenDocumentsMatch.*; + +import java.util.Arrays; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Sum; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + */ +class MergeOperationUnitTests { + + private static final String OUT_COLLECTION = "target-collection"; + private static final String OUT_DB = "target-db"; + + private static final Document OUT = new Document("db", OUT_DB).append("coll", OUT_COLLECTION); + + @Test // DATAMONGO-2363 + void justCollection() { + + assertThat(mergeInto(OUT_COLLECTION).toDocument(DEFAULT_CONTEXT)).isEqualTo(new Document("$merge", OUT_COLLECTION)); + } + + @Test // DATAMONGO-2363 + void collectionInDatabase() { + + assertThat(merge().intoCollection(OUT_COLLECTION).inDatabase("target-db").build().toDocument(DEFAULT_CONTEXT)) + .isEqualTo(new Document("$merge", new Document("into", OUT))); + } + + @Test // DATAMONGO-2363 + void singleOn() { + + assertThat(merge().intoCollection(OUT_COLLECTION).on("id-field").build().toDocument(DEFAULT_CONTEXT)) + .isEqualTo(new Document("$merge", new Document("into", OUT_COLLECTION).append("on", "id-field"))); + } + + @Test // DATAMONGO-2363 + void multipleOn() { + + assertThat(merge().intoCollection(OUT_COLLECTION).on("field-1", "field-2").build().toDocument(DEFAULT_CONTEXT)) + .isEqualTo(new Document("$merge", + new Document("into", OUT_COLLECTION).append("on", Arrays.asList("field-1", "field-2")))); + } + + @Test // DATAMONGO-2363 + void collectionAndSimpleArgs() { + + assertThat(merge().intoCollection(OUT_COLLECTION).on("_id").whenMatched(replaceDocument()) + .whenNotMatched(WhenDocumentsDontMatch.insertNewDocument()).build().toDocument(DEFAULT_CONTEXT)) + .isEqualTo(new Document("$merge", new Document("into", OUT_COLLECTION).append("on", "_id") + .append("whenMatched", "replace").append("whenNotMatched", "insert"))); + } + + @Test // DATAMONGO-2363 + void whenMatchedWithAggregation() { + + String expected = "{ \"$merge\" : {\"into\": \"" + OUT_COLLECTION + "\", \"whenMatched\": [" + + "{ \"$addFields\" : {" // + + "\"thumbsup\": { \"$sum\":[ \"$thumbsup\", \"$$new.thumbsup\" ] }," + + "\"thumbsdown\": { \"$sum\": [ \"$thumbsdown\", \"$$new.thumbsdown\" ] } } } ]" // + + "} }"; + + Aggregation update = Aggregation + .newAggregation(AddFieldsOperation.addField("thumbsup").withValueOf(Sum.sumOf("thumbsup").and("$$new.thumbsup")) + .addField("thumbsdown").withValueOf(Sum.sumOf("thumbsdown").and("$$new.thumbsdown")).build()); + + assertThat( + merge().intoCollection(OUT_COLLECTION).whenDocumentsMatchApply(update).build().toDocument(DEFAULT_CONTEXT)) + .isEqualTo(Document.parse(expected)); + } + + @Test // DATAMONGO-2363 + public void mapsFieldNames() { + + assertThat(merge().intoCollection("newrestaurants").on("date", "postCode").build() + .toDocument(contextFor(Restaurant.class))).isEqualTo( + Document.parse("{ \"$merge\": { \"into\": \"newrestaurants\", \"on\": [ \"date\", \"post_code\" ] } }")); + } + + private static AggregationOperationContext contextFor(@Nullable Class type) { + + if (type == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + MappingMongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, + new MongoMappingContext()); + mongoConverter.afterPropertiesSet(); + + return new TypeBasedAggregationOperationContext(type, mongoConverter.getMappingContext(), + new QueryMapper(mongoConverter)).continueOnMissingFieldReference(); + } + + static class Restaurant { + + @Field("post_code") String postCode; + } +} diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index dc84a60935..e6ab1684d3 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -9,6 +9,7 @@ * Removal of `_id` flattening for composite Id's when using `MongoTemplate` aggregations. * Apply pagination when using GridFS `find(Query)`. * <> via `@Sharded`. +* `$merge` and `$addFields` aggregation pipeline stages. [[new-features.2-2-0]] == What's New in Spring Data MongoDB 2.2 From c829387c8260936276e46b791e135468546c9c77 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 9 Mar 2020 14:08:28 +0100 Subject: [PATCH 0096/1381] DATAMONGO-2363 - Polishing. Introduce support for SpEL aggregation expressions for AddFields and Set operations. Rearrange methods. Make fields final where possible. Original pull request: #801. --- .../core/aggregation/AddFieldsOperation.java | 17 +++- .../mongodb/core/aggregation/Aggregation.java | 82 ++++++++++--------- .../core/aggregation/AggregationUpdate.java | 2 +- .../DocumentEnhancingOperation.java | 47 ++++++++++- .../core/aggregation/MergeOperation.java | 65 +++++++++------ .../core/aggregation/SetOperation.java | 19 ++++- .../AddFieldsOperationUnitTests.java | 17 +++- .../aggregation/MergeOperationUnitTests.java | 4 +- .../aggregation/SetOperationUnitTests.java | 32 +++++--- 9 files changed, 202 insertions(+), 83 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java index 984cfdc8ca..8ebc744adf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java @@ -151,6 +151,13 @@ public AddFieldsOperationBuilder withValueOf(Object value) { valueMap.put(field, value instanceof String ? Fields.fields((String) value) : value); return AddFieldsOperationBuilder.this; } + + @Override + public AddFieldsOperationBuilder withValueOfExpression(String operation, Object... values) { + + valueMap.put(field, new ExpressionProjection(operation, values)); + return AddFieldsOperationBuilder.this; + } }; } @@ -179,7 +186,15 @@ public interface ValueAppender { * @return new instance of {@link AddFieldsOperation}. */ AddFieldsOperationBuilder withValueOf(Object value); - } + /** + * Adds a generic projection for the current field. + * + * @param operation the operation key, e.g. {@code $add}. + * @param values the values to be set for the projection operation. + * @return new instance of {@link AddFieldsOperation}. + */ + AddFieldsOperationBuilder withValueOfExpression(String operation, Object... values); + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 44376d6e83..efcb26f24a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -119,7 +119,7 @@ public static Aggregation newAggregation(AggregationOperation... operations) { /** * Creates a new {@link AggregationUpdate} from the given {@link AggregationOperation}s. - * + * * @param operations can be {@literal empty} but must not be {@literal null}. * @return new instance of {@link AggregationUpdate}. * @since 3.0 @@ -202,11 +202,16 @@ protected Aggregation(List aggregationOperations, Aggregat Assert.notNull(aggregationOperations, "AggregationOperations must not be null!"); Assert.notNull(options, "AggregationOptions must not be null!"); - // check $out is the last operation if it exists + // check $out/$merge is the last operation if it exists for (AggregationOperation aggregationOperation : aggregationOperations) { + if (aggregationOperation instanceof OutOperation && !isLast(aggregationOperation, aggregationOperations)) { throw new IllegalArgumentException("The $out operator must be the last stage in the pipeline."); } + + if (aggregationOperation instanceof MergeOperation && !isLast(aggregationOperation, aggregationOperations)) { + throw new IllegalArgumentException("The $merge operator must be the last stage in the pipeline."); + } } this.operations = aggregationOperations; @@ -236,6 +241,20 @@ public static String previousOperation() { return "_id"; } + /** + * Obtain an {@link AddFieldsOperationBuilder builder} instance to create a new {@link AddFieldsOperation}. + *

      + * Starting in version 4.2, MongoDB adds a new aggregation pipeline stage {@link AggregationUpdate#set $set} that is + * an alias for {@code $addFields}. + * + * @return new instance of {@link AddFieldsOperationBuilder}. + * @see AddFieldsOperation + * @since 3.0 + */ + public static AddFieldsOperationBuilder addFields() { + return AddFieldsOperation.builder(); + } + /** * Creates a new {@link ProjectionOperation} including the given fields. * @@ -495,6 +514,30 @@ public static MatchOperation match(CriteriaDefinition criteria) { return new MatchOperation(criteria); } + /** + * Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the {@code distanceField}. The + * {@code distanceField} defines output field that contains the calculated distance. + * + * @param query must not be {@literal null}. + * @param distanceField must not be {@literal null} or empty. + * @return + * @since 1.7 + */ + public static GeoNearOperation geoNear(NearQuery query, String distanceField) { + return new GeoNearOperation(query, distanceField); + } + + /** + * Obtain a {@link MergeOperationBuilder builder} instance to create a new {@link MergeOperation}. + * + * @return new instance of {@link MergeOperationBuilder}. + * @see MergeOperation + * @since 3.0 + */ + public static MergeOperationBuilder merge() { + return MergeOperation.builder(); + } + /** * Creates a new {@link OutOperation} using the given collection name. This operation must be the last operation in * the pipeline. @@ -636,41 +679,6 @@ public static Fields bind(String name, String target) { return Fields.from(field(name, target)); } - /** - * Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the {@code distanceField}. The - * {@code distanceField} defines output field that contains the calculated distance. - * - * @param query must not be {@literal null}. - * @param distanceField must not be {@literal null} or empty. - * @return - * @since 1.7 - */ - public static GeoNearOperation geoNear(NearQuery query, String distanceField) { - return new GeoNearOperation(query, distanceField); - } - - /** - * Obtain a {@link MergeOperationBuilder builder} instance to create a new {@link MergeOperation}. - * - * @return new instance of {@link MergeOperationBuilder}. - * @see MergeOperation - * @since 3.0 - */ - public static MergeOperationBuilder merge() { - return MergeOperation.builder(); - } - - /** - * Obtain an {@link AddFieldsOperationBuilder builder} instance to create a new {@link AddFieldsOperation}. - * - * @return new instance of {@link AddFieldsOperationBuilder}. - * @see AddFieldsOperation - * @since 3.0 - */ - public static AddFieldsOperationBuilder addFields() { - return AddFieldsOperation.builder(); - } - /** * Returns a new {@link AggregationOptions.Builder}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index 5866f2a1eb..c97ca3974b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -79,7 +79,7 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { private boolean isolated = false; - private Set keysTouched = new HashSet<>(); + private final Set keysTouched = new HashSet<>(); /** * Create new {@link AggregationUpdate}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java index 9c078de59b..1562bce705 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java @@ -24,16 +24,18 @@ import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation; +import org.springframework.util.Assert; /** - * Base class for common taks required by {@link SetOperation} and {@link AddFieldsOperation}. + * Base class for common tasks required by {@link SetOperation} and {@link AddFieldsOperation}. * * @author Christoph Strobl * @since 3.0 */ abstract class DocumentEnhancingOperation implements InheritsFieldsAggregationOperation { - private Map valueMap; + private final Map valueMap; + private ExposedFields exposedFields = ExposedFields.empty(); protected DocumentEnhancingOperation(Map source) { @@ -112,14 +114,53 @@ private static Object computeValue(Object value, AggregationOperationContext con if (value instanceof Field) { return context.getReference((Field) value).toString(); } + + if (value instanceof ExpressionProjection) { + return ((ExpressionProjection) value).toExpression(context); + } + if (value instanceof AggregationExpression) { return ((AggregationExpression) value).toDocument(context); } + if (value instanceof Collection) { - return ((Collection) value).stream().map(it -> computeValue(it, context)).collect(Collectors.toList()); + return ((Collection) value).stream().map(it -> computeValue(it, context)).collect(Collectors.toList()); } return value; } + /** + * A {@link AggregationExpression} based on a SpEL expression. + * + * @author Mark Paluch + */ + static class ExpressionProjection { + + private static final SpelExpressionTransformer TRANSFORMER = new SpelExpressionTransformer(); + + private final String expression; + private final Object[] params; + + /** + * Creates a new {@link ProjectionOperation.ExpressionProjectionOperationBuilder.ExpressionProjection} for the given + * field, SpEL expression and parameters. + * + * @param expression must not be {@literal null} or empty. + * @param parameters must not be {@literal null}. + */ + ExpressionProjection(String expression, Object[] parameters) { + + Assert.notNull(expression, "Expression must not be null!"); + Assert.notNull(parameters, "Parameters must not be null!"); + + this.expression = expression; + this.params = parameters.clone(); + } + + Object toExpression(AggregationOperationContext context) { + return TRANSFORMER.transform(expression, context, params); + } + } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java index 188f9d72db..cae54d3944 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java @@ -33,8 +33,8 @@ /** * Encapsulates the {@code $merge}-operation. *

      - * We recommend to use the {@link MergeOperationBuilder builder} via {@link MergeOperation#builder()} instead of creating - * instances of this class directly. + * We recommend to use the {@link MergeOperationBuilder builder} via {@link MergeOperation#builder()} instead of + * creating instances of this class directly. * * @see MongoDB Documentation * @author Christoph Strobl @@ -42,15 +42,15 @@ */ public class MergeOperation implements FieldsExposingAggregationOperation, InheritsFieldsAggregationOperation { - private MergeOperationTarget into; - private UniqueMergeId on; - private @Nullable Let let; - private @Nullable WhenDocumentsMatch whenMatched; - private @Nullable WhenDocumentsDontMatch whenNotMatched; + private final MergeOperationTarget into; + private final UniqueMergeId on; + private final @Nullable Let let; + private final @Nullable WhenDocumentsMatch whenMatched; + private final @Nullable WhenDocumentsDontMatch whenNotMatched; /** * Create new instance of {@link MergeOperation}. - * + * * @param into the target (collection and database) * @param on the unique identifier. Can be {@literal null}. * @param let exposed variables for {@link WhenDocumentsMatch#updateWith(Aggregation)}. Can be {@literal null}. @@ -63,7 +63,7 @@ public MergeOperation(MergeOperationTarget into, UniqueMergeId on, @Nullable Let @Nullable WhenDocumentsMatch whenMatched, @Nullable WhenDocumentsDontMatch whenNotMatched) { Assert.notNull(into, "Into must not be null! Please provide a target collection."); - Assert.notNull(on, "On must not be null! Use Collections.emptySet() instead."); + Assert.notNull(on, "On must not be null! Use UniqueMergeId.id() instead."); this.into = into; this.on = on; @@ -93,7 +93,7 @@ public static MergeOperationBuilder builder() { } /* - * (non-Javadoc) + * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.Aggregation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) */ @Override @@ -109,15 +109,17 @@ public Document toDocument(AggregationOperationContext context) { if (!on.isJustIdField()) { $merge.putAll(on.toDocument(context)); } + if (let != null) { $merge.append("let", let.toDocument(context).get("$let", Document.class).get("vars")); } + if (whenMatched != null) { $merge.putAll(whenMatched.toDocument(context)); } + if (whenNotMatched != null) { $merge.putAll(whenNotMatched.toDocument(context)); - } return new Document("$merge", $merge); @@ -159,13 +161,12 @@ private boolean isJustCollection() { * collection. * * @author Christoph Strobl - * @since 2.3 */ public static class UniqueMergeId { private static final UniqueMergeId ID = new UniqueMergeId(Collections.emptyList()); - private Collection uniqueIdentifier; + private final Collection uniqueIdentifier; private UniqueMergeId(Collection uniqueIdentifier) { this.uniqueIdentifier = uniqueIdentifier; @@ -173,6 +174,8 @@ private UniqueMergeId(Collection uniqueIdentifier) { public static UniqueMergeId ofIdFields(String... fields) { + Assert.noNullElements(fields, "Fields must not contain null values!"); + if (ObjectUtils.isEmpty(fields)) { return id(); } @@ -182,7 +185,7 @@ public static UniqueMergeId ofIdFields(String... fields) { /** * Merge Documents by using the MongoDB {@literal _id} field. - * + * * @return */ public static UniqueMergeId id() { @@ -206,19 +209,19 @@ Document toDocument(AggregationOperationContext context) { * If not stated explicitly via {@link MergeOperationTarget#inDatabase(String)} the {@literal collection} is created * in the very same {@literal database}. In this case {@code into} is just a single String holding the collection * name.
      - * + * *

       	 *     into: "target-collection-name"
       	 * 
      - * + * * If the collection needs to be in a different database {@code into} will be a {@link Document} like the following - * + * *
       	 * {
       	 * 	into: {}
       	 * }
       	 * 
      - * + * * @author Christoph Strobl * @since 2.3 */ @@ -267,7 +270,7 @@ Document toDocument(AggregationOperationContext context) { /** * Value Object specifying how to deal with a result document that matches an existing document in the collection * based on the fields of the {@code on} property describing the unique identifier. - * + * * @author Christoph Strobl * @since 2.3 */ @@ -354,7 +357,7 @@ Document toDocument(AggregationOperationContext context) { /** * Value Object specifying how to deal with a result document that do not match an existing document in the collection * based on the fields of the {@code on} property describing the unique identifier. - * + * * @author Christoph Strobl * @since 2.3 */ @@ -363,9 +366,18 @@ public static class WhenDocumentsDontMatch { private final String value; private WhenDocumentsDontMatch(String value) { + + Assert.notNull(value, "Value must not be null!"); + this.value = value; } + /** + * Factory method creating {@link WhenDocumentsDontMatch} from a {@code value} literal. + * + * @param value + * @return new instance of {@link WhenDocumentsDontMatch}. + */ public static WhenDocumentsDontMatch whenNotMatchedOf(String value) { return new WhenDocumentsDontMatch(value); } @@ -412,7 +424,7 @@ public static class MergeOperationBuilder { private String collection; private @Nullable String database; - private @Nullable UniqueMergeId id; + private UniqueMergeId id = UniqueMergeId.id(); private @Nullable Let let; private @Nullable WhenDocumentsMatch whenMatched; private @Nullable WhenDocumentsDontMatch whenNotMatched; @@ -447,7 +459,7 @@ public MergeOperationBuilder inDatabase(String database) { /** * Define the target to store results in. - * + * * @param into must not be {@literal null}. * @return this. */ @@ -484,7 +496,7 @@ public MergeOperationBuilder on(String... fields) { /** * Set the identifier that determines if a results document matches an already existing document in the output * collection. - * + * * @param id must not be {@literal null}. * @return this. */ @@ -497,7 +509,7 @@ public MergeOperationBuilder id(UniqueMergeId id) { /** * Expose the variables defined by {@link Let} to the {@link WhenDocumentsMatch#updateWith(Aggregation) update * aggregation}. - * + * * @param let the variable expressions * @return this. */ @@ -520,7 +532,7 @@ public MergeOperationBuilder exposeVariablesOf(Let let) { /** * The action to take place when documents already exist in the target collection. - * + * * @param whenMatched must not be {@literal null}. * @return this. */ @@ -576,8 +588,7 @@ public MergeOperationBuilder whenDocumentsDontMatch(WhenDocumentsDontMatch whenN * @return new instance of {@link MergeOperation}. */ public MergeOperation build() { - return new MergeOperation(new MergeOperationTarget(database, collection), id != null ? id : UniqueMergeId.id(), - let, whenMatched, whenNotMatched); + return new MergeOperation(new MergeOperationTarget(database, collection), id, let, whenMatched, whenNotMatched); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index 5516ece3d5..b9f43d5d3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -25,7 +25,7 @@ /** * Adds new fields to documents. {@code $set} outputs documents that contain all existing fields from the input * documents and newly added fields. - * + * *
        * SetOperation.set("totalHomework").toValue("A+").and().set("totalQuiz").toValue("B-")
        * 
      @@ -143,6 +143,13 @@ public SetOperation toValueOf(Object value) { valueMap.put(field, value instanceof String ? Fields.fields((String) value) : value); return FieldAppender.this.build(); } + + @Override + public SetOperation withValueOfExpression(String operation, Object... values) { + + valueMap.put(field, new ExpressionProjection(operation, values)); + return FieldAppender.this.build(); + } }; } @@ -152,6 +159,7 @@ private SetOperation build() { /** * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ public interface ValueAppender { @@ -171,6 +179,15 @@ public interface ValueAppender { * @return new instance of {@link SetOperation}. */ SetOperation toValueOf(Object value); + + /** + * Adds a generic projection for the current field. + * + * @param operation the operation key, e.g. {@code $add}. + * @param values the values to be set for the projection operation. + * @return new instance of {@link SetOperation}. + */ + SetOperation withValueOfExpression(String operation, Object... values); } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java index 829a1ba8a7..8a6c0b0f08 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperationUnitTests.java @@ -29,7 +29,10 @@ import org.springframework.lang.Nullable; /** + * Unit tests for {@link AddFieldsOperation}. + * * @author Christoph Strobl + * @author Mark Paluch */ class AddFieldsOperationUnitTests { @@ -92,6 +95,17 @@ void rendersNestedMappedTargetValueFieldReferenceCorrectly() { "{\"$addFields\" : {\"scoresWithMappedField.student_name\":\"$scoresWithMappedField.home_work\"}}")); } + @Test // DATAMONGO-2363 + void appliesSpelExpressionCorrectly() { + + AddFieldsOperation operation = AddFieldsOperation.builder().addField("totalHomework") + .withValueOfExpression("sum(homework) * [0]", 2) // + .build(); + + assertThat(operation.toPipelineStages(contextFor(ScoresWrapper.class))).contains( + Document.parse("{\"$addFields\" : {\"totalHomework\": { $multiply : [{ \"$sum\" : [\"$homework\"] }, 2] }}}")); + } + @Test // DATAMONGO-2363 void rendersTargetValueExpressionCorrectly() { @@ -105,10 +119,11 @@ void exposesFieldsCorrectly() { ExposedFields fields = AddFieldsOperation.builder().addField("totalHomework").withValue("A+") // .addField("totalQuiz").withValue("B-") // - .build().getFields(); + .addField("computed").withValueOfExpression("totalHomework").build().getFields(); assertThat(fields.getField("totalHomework")).isNotNull(); assertThat(fields.getField("totalQuiz")).isNotNull(); + assertThat(fields.getField("computed")).isNotNull(); assertThat(fields.getField("does-not-exist")).isNull(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java index 509dfc48dd..60a52fe7ac 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MergeOperationUnitTests.java @@ -33,6 +33,8 @@ import org.springframework.lang.Nullable; /** + * Unit tests for {@link MergeOperation}. + * * @author Christoph Strobl */ class MergeOperationUnitTests { @@ -98,7 +100,7 @@ void whenMatchedWithAggregation() { } @Test // DATAMONGO-2363 - public void mapsFieldNames() { + void mapsFieldNames() { assertThat(merge().intoCollection("newrestaurants").on("date", "postCode").build() .toDocument(contextFor(Restaurant.class))).isEqualTo( diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java index a3c3203fa9..f0162333da 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java @@ -32,30 +32,31 @@ * Unit tests for {@link SetOperation}. * * @author Christoph Strobl + * @author Mark Paluch */ -public class SetOperationUnitTests { +class SetOperationUnitTests { @Test // DATAMONGO-2331 - public void raisesErrorOnNullField() { + void raisesErrorOnNullField() { assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new SetOperation(null, "value")); } @Test // DATAMONGO-2331 - public void rendersFieldReferenceCorrectly() { + void rendersFieldReferenceCorrectly() { assertThat(new SetOperation("name", "value").toPipelineStages(contextFor(Scores.class))) .containsExactly(Document.parse("{\"$set\" : {\"name\":\"value\"}}")); } @Test // DATAMONGO-2331 - public void rendersMappedFieldReferenceCorrectly() { + void rendersMappedFieldReferenceCorrectly() { assertThat(new SetOperation("student", "value").toPipelineStages(contextFor(ScoresWithMappedField.class))) .containsExactly(Document.parse("{\"$set\" : {\"student_name\":\"value\"}}")); } @Test // DATAMONGO-2331 - public void rendersNestedMappedFieldReferenceCorrectly() { + void rendersNestedMappedFieldReferenceCorrectly() { assertThat( new SetOperation("scoresWithMappedField.student", "value").toPipelineStages(contextFor(ScoresWrapper.class))) @@ -63,14 +64,14 @@ public void rendersNestedMappedFieldReferenceCorrectly() { } @Test // DATAMONGO-2331 - public void rendersTargetValueFieldReferenceCorrectly() { + void rendersTargetValueFieldReferenceCorrectly() { assertThat(new SetOperation("name", Fields.field("value")).toPipelineStages(contextFor(Scores.class))) .containsExactly(Document.parse("{\"$set\" : {\"name\":\"$value\"}}")); } @Test // DATAMONGO-2331 - public void rendersMappedTargetValueFieldReferenceCorrectly() { + void rendersMappedTargetValueFieldReferenceCorrectly() { assertThat( new SetOperation("student", Fields.field("homework")).toPipelineStages(contextFor(ScoresWithMappedField.class))) @@ -78,7 +79,7 @@ public void rendersMappedTargetValueFieldReferenceCorrectly() { } @Test // DATAMONGO-2331 - public void rendersNestedMappedTargetValueFieldReferenceCorrectly() { + void rendersNestedMappedTargetValueFieldReferenceCorrectly() { assertThat(new SetOperation("scoresWithMappedField.student", Fields.field("scoresWithMappedField.homework")) .toPipelineStages(contextFor(ScoresWrapper.class))) @@ -86,8 +87,18 @@ public void rendersNestedMappedTargetValueFieldReferenceCorrectly() { .parse("{\"$set\" : {\"scoresWithMappedField.student_name\":\"$scoresWithMappedField.home_work\"}}")); } + @Test // DATAMONGO-2363 + void appliesSpelExpressionCorrectly() { + + SetOperation operation = SetOperation.builder().set("totalHomework").withValueOfExpression("sum(homework) * [0]", + 2); + + assertThat(operation.toPipelineStages(contextFor(AddFieldsOperationUnitTests.ScoresWrapper.class))).contains( + Document.parse("{\"$set\" : {\"totalHomework\": { $multiply : [{ \"$sum\" : [\"$homework\"] }, 2] }}}")); + } + @Test // DATAMONGO-2331 - public void rendersTargetValueExpressionCorrectly() { + void rendersTargetValueExpressionCorrectly() { assertThat(SetOperation.builder().set("totalHomework").toValueOf(ArithmeticOperators.valueOf("homework").sum()) .toPipelineStages(contextFor(Scores.class))) @@ -95,7 +106,7 @@ public void rendersTargetValueExpressionCorrectly() { } @Test // DATAMONGO-2331 - public void exposesFieldsCorrectly() { + void exposesFieldsCorrectly() { ExposedFields fields = SetOperation.builder().set("totalHomework").toValue("A+") // .and() // @@ -138,5 +149,4 @@ static class ScoresWrapper { Scores scores; ScoresWithMappedField scoresWithMappedField; } - } From 7b34a602ed9234511496d104d55adf2603f785bf Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 10 Mar 2020 13:55:41 +0100 Subject: [PATCH 0097/1381] DATAMONGO-2355 - Declare concrete Template API class type on AbstractReactiveMongoConfiguration. We now declare bean methods returning Template API types with their concrete implementation to allow for improved introspection of bean definitions. --- .../data/mongodb/config/AbstractMongoClientConfiguration.java | 3 ++- .../mongodb/config/AbstractReactiveMongoConfiguration.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index 2bac4e54a0..5691df8288 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -15,11 +15,11 @@ */ package org.springframework.data.mongodb.config; -import com.mongodb.MongoClientSettings.Builder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.SpringDataMongoDB; +import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -29,6 +29,7 @@ import org.springframework.lang.Nullable; import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java index d64bcfc914..8b538f9d0d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java @@ -60,7 +60,7 @@ public MongoClient reactiveMongoClient() { * @return never {@literal null}. */ @Bean - public ReactiveMongoOperations reactiveMongoTemplate() throws Exception { + public ReactiveMongoTemplate reactiveMongoTemplate() throws Exception { return new ReactiveMongoTemplate(reactiveMongoDbFactory(), mappingMongoConverter()); } From df43d7fcdb7c2bedf1d2265ed12206232267e0d2 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 10 Mar 2020 14:17:37 +0100 Subject: [PATCH 0098/1381] =?UTF-8?q?DATAMONGO-2355=20-=20Refactor=20Abstr?= =?UTF-8?q?act=E2=80=A6Configuration=20classes=20to=20avoid=20need=20for?= =?UTF-8?q?=20cglib=20proxies.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configuration methods now use parameter injections to avoid the need for cglib subclassing. --- .../AbstractMongoClientConfiguration.java | 32 +++++++++---------- .../AbstractReactiveMongoConfiguration.java | 27 +++++++++------- .../config/MongoConfigurationSupport.java | 7 ++-- .../AbstractMongoConfigurationUnitTests.java | 10 +++--- ...ctReactiveMongoConfigurationUnitTests.java | 10 +++--- .../mongodb/core/TestMongoConfiguration.java | 14 ++++++-- src/main/asciidoc/upgrading.adoc | 3 ++ 7 files changed, 62 insertions(+), 41 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index 5691df8288..a9635c9743 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -19,13 +19,14 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.SpringDataMongoDB; -import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.lang.Nullable; import com.mongodb.MongoClientSettings; @@ -40,7 +41,7 @@ * @since 2.1 * @see MongoConfigurationSupport */ -@Configuration +@Configuration(proxyBeanMethods = false) public abstract class AbstractMongoClientConfiguration extends MongoConfigurationSupport { /** @@ -59,11 +60,12 @@ public MongoClient mongoClient() { /** * Creates a {@link MongoTemplate}. * - * @return + * @see #mongoDbFactory() + * @see #mappingMongoConverter(MongoDatabaseFactory, MongoCustomConversions, MongoMappingContext) */ @Bean - public MongoTemplate mongoTemplate() throws Exception { - return new MongoTemplate(mongoDbFactory(), mappingMongoConverter()); + public MongoTemplate mongoTemplate(MongoDatabaseFactory databaseFactory, MappingMongoConverter converter) { + return new MongoTemplate(databaseFactory, converter); } /** @@ -71,8 +73,7 @@ public MongoTemplate mongoTemplate() throws Exception { * {@link MongoTemplate}. Will use the {@link MongoClient} instance configured in {@link #mongoClient()}. * * @see #mongoClient() - * @see #mongoTemplate() - * @return + * @see #mongoTemplate(MongoDatabaseFactory, MappingMongoConverter) */ @Bean public MongoDatabaseFactory mongoDbFactory() { @@ -99,21 +100,20 @@ protected String getMappingBasePackage() { /** * Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and - * {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied. + * {@link #mongoMappingContext(MongoCustomConversions)}. Will get {@link #customConversions()} applied. * * @see #customConversions() - * @see #mongoMappingContext() + * @see #mongoMappingContext(MongoCustomConversions) * @see #mongoDbFactory() - * @return - * @throws Exception */ @Bean - public MappingMongoConverter mappingMongoConverter() throws Exception { + public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory databaseFactory, + MongoCustomConversions customConversions, MongoMappingContext mappingContext) { - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); - MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext()); - converter.setCustomConversions(customConversions()); - converter.setCodecRegistryProvider(mongoDbFactory()); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(databaseFactory); + MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext); + converter.setCustomConversions(customConversions); + converter.setCodecRegistryProvider(databaseFactory); return converter; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java index 8b538f9d0d..f02fbaabf0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java @@ -23,7 +23,9 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import com.mongodb.MongoClientSettings; import com.mongodb.MongoClientSettings.Builder; @@ -38,7 +40,7 @@ * @since 2.0 * @see MongoConfigurationSupport */ -@Configuration +@Configuration(proxyBeanMethods = false) public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurationSupport { /** @@ -57,11 +59,14 @@ public MongoClient reactiveMongoClient() { /** * Creates {@link ReactiveMongoOperations}. * + * @see #reactiveMongoDbFactory() + * @see #mappingMongoConverter(ReactiveMongoDatabaseFactory, MongoCustomConversions, MongoMappingContext) * @return never {@literal null}. */ @Bean - public ReactiveMongoTemplate reactiveMongoTemplate() throws Exception { - return new ReactiveMongoTemplate(reactiveMongoDbFactory(), mappingMongoConverter()); + public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory databaseFactory, + MappingMongoConverter mongoConverter) { + return new ReactiveMongoTemplate(databaseFactory, mongoConverter); } /** @@ -69,7 +74,7 @@ public ReactiveMongoTemplate reactiveMongoTemplate() throws Exception { * {@link MongoClient} instance configured in {@link #reactiveMongoClient()}. * * @see #reactiveMongoClient() - * @see #reactiveMongoTemplate() + * @see #reactiveMongoTemplate(ReactiveMongoDatabaseFactory, MappingMongoConverter) * @return never {@literal null}. */ @Bean @@ -79,20 +84,20 @@ public ReactiveMongoDatabaseFactory reactiveMongoDbFactory() { /** * Creates a {@link MappingMongoConverter} using the configured {@link #reactiveMongoDbFactory()} and - * {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied. + * {@link #mongoMappingContext(MongoCustomConversions)}. Will get {@link #customConversions()} applied. * * @see #customConversions() - * @see #mongoMappingContext() + * @see #mongoMappingContext(MongoCustomConversions) * @see #reactiveMongoDbFactory() * @return never {@literal null}. - * @throws Exception */ @Bean - public MappingMongoConverter mappingMongoConverter() throws Exception { + public MappingMongoConverter mappingMongoConverter(ReactiveMongoDatabaseFactory databaseFactory, + MongoCustomConversions customConversions, MongoMappingContext mappingContext) { - MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mongoMappingContext()); - converter.setCustomConversions(customConversions()); - converter.setCodecRegistryProvider(reactiveMongoDbFactory()); + MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); + converter.setCustomConversions(customConversions); + converter.setCodecRegistryProvider(databaseFactory); return converter; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index 445c4ef793..efef317d85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -80,11 +80,12 @@ protected Collection getMappingBasePackages() { * @throws ClassNotFoundException */ @Bean - public MongoMappingContext mongoMappingContext() throws ClassNotFoundException { + public MongoMappingContext mongoMappingContext(MongoCustomConversions customConversions) + throws ClassNotFoundException { MongoMappingContext mappingContext = new MongoMappingContext(); mappingContext.setInitialEntitySet(getInitialEntitySet()); - mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder()); + mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder()); mappingContext.setFieldNamingStrategy(fieldNamingStrategy()); mappingContext.setAutoIndexCreation(autoIndexCreation()); @@ -103,7 +104,7 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException { * @return must not be {@literal null}. */ @Bean - public CustomConversions customConversions() { + public MongoCustomConversions customConversions() { return MongoCustomConversions.create(this::configureConverters); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index d51b6d234b..b37f26144b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -34,6 +34,7 @@ import org.springframework.context.support.AbstractApplicationContext; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.convert.MongoTypeMapper; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.Document; @@ -90,7 +91,7 @@ public void containsMongoDbFactoryButNoMongoBean() { public void returnsUninitializedMappingContext() throws Exception { SampleMongoConfiguration configuration = new SampleMongoConfiguration(); - MongoMappingContext context = configuration.mongoMappingContext(); + MongoMappingContext context = configuration.mongoMappingContext(configuration.customConversions()); assertThat(context.getPersistentEntities()).isEmpty(); context.initialize(); @@ -159,11 +160,10 @@ public MongoClient mongoClient() { return MongoClients.create(); } - @Bean @Override - public MappingMongoConverter mappingMongoConverter() throws Exception { - - MappingMongoConverter converter = super.mappingMongoConverter(); + public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory databaseFactory, + MongoCustomConversions customConversions, MongoMappingContext mappingContext) { + MappingMongoConverter converter = super.mappingMongoConverter(databaseFactory, customConversions, mappingContext); converter.setTypeMapper(typeMapper()); return converter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java index a89bdd2993..5904651c70 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java @@ -32,8 +32,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.convert.MongoTypeMapper; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.Document; @@ -89,7 +91,7 @@ public void containsMongoDbFactoryButNoMongoBean() { public void returnsUninitializedMappingContext() throws Exception { SampleMongoConfiguration configuration = new SampleMongoConfiguration(); - MongoMappingContext context = configuration.mongoMappingContext(); + MongoMappingContext context = configuration.mongoMappingContext(configuration.customConversions()); assertThat(context.getPersistentEntities()).isEmpty(); context.initialize(); @@ -158,11 +160,11 @@ public MongoClient reactiveMongoClient() { return MongoTestUtils.reactiveClient(); } - @Bean @Override - public MappingMongoConverter mappingMongoConverter() throws Exception { + public MappingMongoConverter mappingMongoConverter(ReactiveMongoDatabaseFactory databaseFactory, + MongoCustomConversions customConversions, MongoMappingContext mappingContext) { - MappingMongoConverter converter = super.mappingMongoConverter(); + MappingMongoConverter converter = super.mappingMongoConverter(databaseFactory, customConversions, mappingContext); converter.setTypeMapper(typeMapper()); return converter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java index 9a9cd95e9a..a5347dab4c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java @@ -21,9 +21,11 @@ import java.util.Set; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.CustomConversions; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -37,6 +39,14 @@ public String getDatabaseName() { return "database"; } + @Primary + @Bean + @Override + public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory databaseFactory, + MongoCustomConversions customConversions, MongoMappingContext mappingContext) { + return super.mappingMongoConverter(databaseFactory, customConversions, mappingContext); + } + @Override @Bean public MongoClient mongoClient() { @@ -49,7 +59,7 @@ public String getMappingBasePackage() { } @Override - public CustomConversions customConversions() { + public MongoCustomConversions customConversions() { List> converters = new ArrayList<>(2); converters.add(new org.springframework.data.mongodb.core.PersonReadConverter()); diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index 5de900855e..d2111515b6 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -37,6 +37,9 @@ Uses `MongoClientSettings` instead of `MongoClientOptions`. | `ReactiveMongoClientSettingsFactoryBean` | Now produces `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` + +| `AbstractMongoClientConfiguration`, `AbstractReactiveMongoConfiguration` +| Configuration methods use parameter injection instead of calling local methods to avoid the need for cglib proxies |=== .Removed Java API: From d0eb76946e1292630525b5dc50c4b9225028dbf7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 11 Mar 2020 09:14:53 +0100 Subject: [PATCH 0099/1381] DATAMONGO-2491 - Adapt to Mockito 3.3 changes. Mockito reports falsely unnecessary stubbings so we're switching to the silent runner for these cases. --- .../data/mongodb/core/DefaultBulkOperationsUnitTests.java | 5 +++-- .../ReactiveMongoPersistentEntityIndexCreatorUnitTests.java | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 98fc767f0f..47302d2ac8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -69,6 +69,7 @@ import com.mongodb.WriteError; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.BulkWriteOptions; import com.mongodb.client.model.DeleteManyModel; import com.mongodb.client.model.InsertOneModel; import com.mongodb.client.model.ReplaceOneModel; @@ -281,7 +282,7 @@ void bulkInsertEmitsEventsCorrectly() { void noAfterSaveEventOnFailure() { ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); - when(collection.bulkWrite(anyList(), any())).thenThrow(new MongoWriteException( + when(collection.bulkWrite(anyList(), any(BulkWriteOptions.class))).thenThrow(new MongoWriteException( new WriteError(89, "NetworkTimeout", new BsonDocument("hi", new BsonString("there!"))), null)); ops = new DefaultBulkOperations(template, "collection-1", @@ -294,12 +295,12 @@ void noAfterSaveEventOnFailure() { try { ops.execute(); + fail("Missing MongoWriteException"); } catch (MongoWriteException expected) { } verify(eventPublisher).publishEvent(any(BeforeSaveEvent.class)); - verify(eventPublisher, never()).publishEvent(any(AfterSaveEvent.class)); } @Test // DATAMONGO-2330 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java index 10374088e4..1a4e12b29e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java @@ -30,6 +30,8 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; @@ -50,6 +52,7 @@ * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { private ReactiveIndexOperations indexOperations; From 8f2c806403c0a6bb4b8c9e85d7adf3dbf1fbe225 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 11 Mar 2020 09:46:17 +0100 Subject: [PATCH 0100/1381] DATAMONGO-2473 - Updated changelog. --- src/main/resources/changelog.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 4fe69366c9..659de9ed2e 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,20 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.M4 (2020-03-11) +---------------------------------------- +* DATAMONGO-2491 - Adapt to Mockito 3.3 changes. +* DATAMONGO-2489 - Upgrade to MongoDB Driver 4.0. +* DATAMONGO-2481 - Speed up build. +* DATAMONGO-2478 - NPE when using Query annotation and with sort and pageable. +* DATAMONGO-2476 - JsonParseException: JSON reader was expecting a value but found '}'. +* DATAMONGO-2474 - Upgrade to MongoDB Driver 4.0.0-rc0. +* DATAMONGO-2473 - Release 3.0 M4 (Neumann). +* DATAMONGO-2363 - Add support for $merge aggregation stage. +* DATAMONGO-2355 - Revise Abstract…MongoConfiguration to expose more bean detail and avoid proxying. +* DATAMONGO-2341 - Support shard key derivation. + + Changes in version 2.2.5.RELEASE (2020-02-26) --------------------------------------------- * DATAMONGO-2478 - NPE when using Query annotation and with sort and pageable. @@ -2935,3 +2949,4 @@ Repository + From 4d73d76b9f70eda993b26a698ec18cbf9883fee8 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 11 Mar 2020 09:46:29 +0100 Subject: [PATCH 0101/1381] DATAMONGO-2473 - Prepare 3.0 M4 (Neumann). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9d4d60f25a..365a73a76e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M4 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.M4 4.0.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 9097e23c55..f1f11a2296 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 M3 +Spring Data MongoDB 3.0 M4 Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -11,3 +11,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From fde49f2a5a3723167a434b7b06e7e8b0185e84c2 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 11 Mar 2020 09:47:07 +0100 Subject: [PATCH 0102/1381] DATAMONGO-2473 - Release version 3.0 M4 (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 365a73a76e..76b4b30c7a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M4 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..129c718960 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M4 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..d37d708496 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M4 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 872db5d428..940bb704cf 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.M4 ../pom.xml From b68079c4214dd04a5526f757cbd63d2daf52462d Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 11 Mar 2020 09:57:41 +0100 Subject: [PATCH 0103/1381] DATAMONGO-2473 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 76b4b30c7a..365a73a76e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M4 + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 129c718960..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M4 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index d37d708496..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M4 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 940bb704cf..872db5d428 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.M4 + 3.0.0.BUILD-SNAPSHOT ../pom.xml From 5a49aa651996faca04a0a0628974b3cbbcf25b31 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 11 Mar 2020 09:57:42 +0100 Subject: [PATCH 0104/1381] DATAMONGO-2473 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 365a73a76e..9d4d60f25a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.M4 + 2.3.0.BUILD-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.M4 + 2.3.0.BUILD-SNAPSHOT 4.0.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 7f7be5e47d2bd5c180ef2709fc2e556fc8a8d8dd Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 11 Mar 2020 10:30:28 +0100 Subject: [PATCH 0105/1381] DATAMONGO-2488 - Fix nested array path field name mapping. Original pull request: #841. --- .../mongodb/core/convert/QueryMapper.java | 33 ++++++++-- .../mongodb/core/convert/UpdateMapper.java | 10 +-- .../core/convert/QueryMapperUnitTests.java | 65 ++++++++++++++++++- 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 713d50b6b6..f7ec113cfd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -24,7 +24,6 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; - import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Example; @@ -175,7 +174,7 @@ public Document getMappedSort(Document sortObject, @Nullable MongoPersistentEnti } Document mappedSort = new Document(); - for(Map.Entry entry : BsonUtils.asMap(sortObject).entrySet()) { + for (Map.Entry entry : BsonUtils.asMap(sortObject).entrySet()) { Field field = createPropertyField(entity, entry.getKey(), mappingContext); mappedSort.put(field.getMappedKey(), entry.getValue()); @@ -1158,7 +1157,7 @@ private boolean isPathToJavaLangClassProperty(PropertyPath path) { * @return */ protected Converter getPropertyConverter() { - return new PositionParameterRetainingPropertyKeyConverter(name); + return new PositionParameterRetainingPropertyKeyConverter(name, mappingContext); } /** @@ -1172,6 +1171,10 @@ protected Converter getAssociationConverter() { return new AssociationConverter(getAssociation()); } + protected MappingContext, MongoPersistentProperty> getMappingContext() { + return mappingContext; + } + /** * @author Christoph Strobl * @since 1.8 @@ -1180,8 +1183,9 @@ static class PositionParameterRetainingPropertyKeyConverter implements Converter private final KeyMapper keyMapper; - public PositionParameterRetainingPropertyKeyConverter(String rawKey) { - this.keyMapper = new KeyMapper(rawKey); + public PositionParameterRetainingPropertyKeyConverter(String rawKey, + MappingContext, MongoPersistentProperty> ctx) { + this.keyMapper = new KeyMapper(rawKey, ctx); } /* @@ -1222,11 +1226,14 @@ public TypeInformation getTypeHint() { static class KeyMapper { private final Iterator iterator; + private final MappingContext, MongoPersistentProperty> mappingContext; - public KeyMapper(String key) { + public KeyMapper(String key, + MappingContext, MongoPersistentProperty> mappingContext) { this.iterator = Arrays.asList(key.split("\\.")).iterator(); this.iterator.next(); + this.mappingContext = mappingContext; } /** @@ -1240,9 +1247,22 @@ protected String mapPropertyName(MongoPersistentProperty property) { StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property)); boolean inspect = iterator.hasNext(); + int depth = 0; while (inspect) { String partial = iterator.next(); + + if (depth > 0 && property.isCollectionLike()) { + + MongoPersistentEntity persistentEntity = mappingContext.getPersistentEntity(property.getComponentType()); + if (persistentEntity != null) { + MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(partial); + if(persistentProperty != null) { + partial = mapPropertyName(persistentProperty); + } + } + } + boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike())); if (isPositional) { @@ -1250,6 +1270,7 @@ protected String mapPropertyName(MongoPersistentProperty property) { } inspect = isPositional && iterator.hasNext(); + depth++; } return mappedName.toString(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java index 5cf86823c5..463c15d4eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java @@ -308,7 +308,7 @@ public String getMappedKey() { */ @Override protected Converter getPropertyConverter() { - return new PositionParameterRetainingPropertyKeyConverter(key); + return new PositionParameterRetainingPropertyKeyConverter(key, getMappingContext()); } /* @@ -317,7 +317,7 @@ protected Converter getPropertyConverter() { */ @Override protected Converter getAssociationConverter() { - return new UpdateAssociationConverter(getAssociation(), key); + return new UpdateAssociationConverter(getMappingContext(), getAssociation(), key); } /** @@ -334,10 +334,12 @@ protected static class UpdateAssociationConverter extends AssociationConverter { * * @param association must not be {@literal null}. */ - public UpdateAssociationConverter(Association association, String key) { + public UpdateAssociationConverter( + MappingContext, MongoPersistentProperty> mappingContext, + Association association, String key) { super(association); - this.mapper = new KeyMapper(key); + this.mapper = new KeyMapper(key, mappingContext); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index e3ab12d40c..a9ecdc88bb 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -36,7 +36,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; - import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -927,6 +926,70 @@ void convertsInWithIdFieldAndObjectIdTypeHintCorrectly() { assertThat(target).isEqualTo(org.bson.Document.parse("{\"_id\": {\"$in\": [{\"$oid\": \"" + id + "\"}]}}")); } + @Test // DATAMONGO-2488 + public void mapsNestedArrayPathCorrectlyForNonMatchingPath() { + + org.bson.Document target = mapper.getMappedObject( + query(where("array.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), + context.getPersistentEntity(Foo.class)); + + assertThat(target).isEqualTo(new org.bson.Document("array.$[some_item].nested.$[other_item]", "value")); + } + + @Test // DATAMONGO-2488 + public void mapsNestedArrayPathCorrectlyForObjectTargetArray() { + + org.bson.Document target = mapper.getMappedObject( + query(where("arrayObj.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), + context.getPersistentEntity(WithNestedArray.class)); + + assertThat(target).isEqualTo(new org.bson.Document("arrayObj.$[some_item].nested.$[other_item]", "value")); + } + + @Test // DATAMONGO-2488 + public void mapsNestedArrayPathCorrectlyForStringTargetArray() { + + org.bson.Document target = mapper.getMappedObject( + query(where("arrayString.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), + context.getPersistentEntity(WithNestedArray.class)); + + assertThat(target).isEqualTo(new org.bson.Document("arrayString.$[some_item].nested.$[other_item]", "value")); + } + + @Test // DATAMONGO-2488 + public void mapsCustomFieldNamesForNestedArrayPathCorrectly() { + + org.bson.Document target = mapper.getMappedObject( + query(where("arrayCustomName.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), + context.getPersistentEntity(WithNestedArray.class)); + + assertThat(target).isEqualTo(new org.bson.Document("arrayCustomName.$[some_item].nes-ted.$[other_item]", "value")); + } + + class WithNestedArray { + + List arrayObj; + List arrayString; + List arrayCustomName; + } + + class NestedArrayOfObj { + List nested; + } + + class NestedArrayOfObjCustomFieldName { + + @Field("nes-ted") List nested; + } + + class NestedArrayOfString { + List nested; + } + + class ArrayObj { + String foo; + } + @Document class Foo { @Id private ObjectId id; From b0b905ddb73b593ee01a3788af8e8cad6a2c3773 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 11 Mar 2020 14:31:24 +0100 Subject: [PATCH 0106/1381] DATAMONGO-2488 - Polishing. Simplify conditional entity check. Reduce test method visibility for JUnit 5. Original pull request: #841. --- .../data/mongodb/core/convert/QueryMapper.java | 15 +++++++-------- .../core/convert/QueryMapperUnitTests.java | 14 +++++++------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index f7ec113cfd..715ba82d5b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1252,14 +1252,13 @@ protected String mapPropertyName(MongoPersistentProperty property) { String partial = iterator.next(); - if (depth > 0 && property.isCollectionLike()) { - - MongoPersistentEntity persistentEntity = mappingContext.getPersistentEntity(property.getComponentType()); - if (persistentEntity != null) { - MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(partial); - if(persistentProperty != null) { - partial = mapPropertyName(persistentProperty); - } + if (depth > 0 && property.isCollectionLike() && property.isEntity() && property.getComponentType() != null) { + + MongoPersistentEntity persistentEntity = mappingContext + .getRequiredPersistentEntity(property.getComponentType()); + MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(partial); + if (persistentProperty != null) { + partial = mapPropertyName(persistentProperty); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index a9ecdc88bb..55e3016955 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -73,9 +73,9 @@ @ExtendWith(MockitoExtension.class) public class QueryMapperUnitTests { - QueryMapper mapper; - MongoMappingContext context; - MappingMongoConverter converter; + private QueryMapper mapper; + private MongoMappingContext context; + private MappingMongoConverter converter; @Mock MongoDatabaseFactory factory; @@ -927,7 +927,7 @@ void convertsInWithIdFieldAndObjectIdTypeHintCorrectly() { } @Test // DATAMONGO-2488 - public void mapsNestedArrayPathCorrectlyForNonMatchingPath() { + void mapsNestedArrayPathCorrectlyForNonMatchingPath() { org.bson.Document target = mapper.getMappedObject( query(where("array.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), @@ -937,7 +937,7 @@ public void mapsNestedArrayPathCorrectlyForNonMatchingPath() { } @Test // DATAMONGO-2488 - public void mapsNestedArrayPathCorrectlyForObjectTargetArray() { + void mapsNestedArrayPathCorrectlyForObjectTargetArray() { org.bson.Document target = mapper.getMappedObject( query(where("arrayObj.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), @@ -947,7 +947,7 @@ public void mapsNestedArrayPathCorrectlyForObjectTargetArray() { } @Test // DATAMONGO-2488 - public void mapsNestedArrayPathCorrectlyForStringTargetArray() { + void mapsNestedArrayPathCorrectlyForStringTargetArray() { org.bson.Document target = mapper.getMappedObject( query(where("arrayString.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), @@ -957,7 +957,7 @@ public void mapsNestedArrayPathCorrectlyForStringTargetArray() { } @Test // DATAMONGO-2488 - public void mapsCustomFieldNamesForNestedArrayPathCorrectly() { + void mapsCustomFieldNamesForNestedArrayPathCorrectly() { org.bson.Document target = mapper.getMappedObject( query(where("arrayCustomName.$[some_item].nested.$[other_item]").is("value")).getQueryObject(), From ee59c6b7748471ed82fd0bc30169a374606709b7 Mon Sep 17 00:00:00 2001 From: Roman Puchkovskiy Date: Mon, 17 Feb 2020 22:43:25 +0400 Subject: [PATCH 0107/1381] DATAMONGO-2479 - Add AfterConvertCallback and AfterSaveCallback (and their reactive versions). Previously, only BeforeConvertCallback and BeforeSaveCallback were supported (and their reactive counterparts). This commit adds support for 'after-convert' and 'after-save' events using entity callbacks feature. Original pull request: #839. --- .../mongodb/core/DefaultBulkOperations.java | 26 ++ .../data/mongodb/core/MongoTemplate.java | 100 +++--- .../mongodb/core/ReactiveMongoTemplate.java | 169 ++++----- .../core/convert/MappingMongoConverter.java | 43 ++- .../mapping/event/AfterConvertCallback.java | 40 +++ .../core/mapping/event/AfterSaveCallback.java | 40 +++ .../event/ReactiveAfterConvertCallback.java | 43 +++ .../event/ReactiveAfterSaveCallback.java | 44 +++ .../core/DefaultBulkOperationsUnitTests.java | 23 +- .../mongodb/core/MongoTemplateUnitTests.java | 315 +++++++++++++++++ .../core/ReactiveMongoTemplateUnitTests.java | 322 ++++++++++++++++++ .../MappingMongoConverterUnitTests.java | 69 ++++ 12 files changed, 1095 insertions(+), 139 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index ee57410352..9c553f2777 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -32,6 +32,7 @@ import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.convert.UpdateMapper; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveCallback; import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; @@ -62,6 +63,7 @@ * @author Minsu Kim * @author Jens Schauder * @author Michail Nikolaev + * @author Roman Puchkovskiy * @since 1.9 */ class DefaultBulkOperations implements BulkOperations { @@ -300,6 +302,7 @@ public com.mongodb.bulk.BulkWriteResult execute() { Assert.state(result != null, "Result must not be null."); models.forEach(this::maybeEmitAfterSaveEvent); + models.forEach(this::maybeInvokeAfterSaveCallback); return result; } finally { @@ -447,6 +450,19 @@ private void maybeEmitAfterSaveEvent(SourceAwareWriteModelHolder it) { } } + private void maybeInvokeAfterSaveCallback(SourceAwareWriteModelHolder it) { + + if (it.getModel() instanceof InsertOneModel) { + + Document target = ((InsertOneModel) it.getModel()).getDocument(); + maybeInvokeAfterSaveCallback(it.getSource(), target); + } else if (it.getModel() instanceof ReplaceOneModel) { + + Document target = ((ReplaceOneModel) it.getModel()).getReplacement(); + maybeInvokeAfterSaveCallback(it.getSource(), target); + } + } + private , T> E maybeEmitEvent(E event) { if (null != bulkOperationContext.getEventPublisher()) { @@ -475,6 +491,16 @@ private Object maybeInvokeBeforeSaveCallback(Object value, Document mappedDocume collectionName); } + private Object maybeInvokeAfterSaveCallback(Object value, Document mappedDocument) { + + if (bulkOperationContext.getEntityCallbacks() == null) { + return value; + } + + return bulkOperationContext.getEntityCallbacks().callback(AfterSaveCallback.class, value, mappedDocument, + collectionName); + } + private static BulkWriteOptions getBulkWriteOptions(BulkMode bulkMode) { BulkWriteOptions options = new BulkWriteOptions(); 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 07a4e2bd63..20055ebbff 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 @@ -33,6 +33,7 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -70,16 +71,7 @@ import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; -import org.springframework.data.mongodb.core.convert.JsonSchemaMapper; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.convert.MongoConverter; -import org.springframework.data.mongodb.core.convert.MongoCustomConversions; -import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper; -import org.springframework.data.mongodb.core.convert.MongoWriter; -import org.springframework.data.mongodb.core.convert.QueryMapper; -import org.springframework.data.mongodb.core.convert.UpdateMapper; +import org.springframework.data.mongodb.core.convert.*; import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.index.IndexOperationsProvider; import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher; @@ -87,16 +79,7 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; -import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent; -import org.springframework.data.mongodb.core.mapping.event.AfterDeleteEvent; -import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent; -import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; -import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback; -import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; -import org.springframework.data.mongodb.core.mapping.event.BeforeDeleteEvent; -import org.springframework.data.mongodb.core.mapping.event.BeforeSaveCallback; -import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent; -import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent; +import org.springframework.data.mongodb.core.mapping.event.*; import org.springframework.data.mongodb.core.mapreduce.GroupBy; import org.springframework.data.mongodb.core.mapreduce.GroupByResults; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; @@ -128,16 +111,7 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; -import com.mongodb.client.AggregateIterable; -import com.mongodb.client.ClientSession; -import com.mongodb.client.DistinctIterable; -import com.mongodb.client.FindIterable; -import com.mongodb.client.MapReduceIterable; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoCursor; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.MongoIterable; +import com.mongodb.client.*; import com.mongodb.client.model.*; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; @@ -166,6 +140,7 @@ * @author Andreas Zink * @author Cimon Lucas * @author Michael J. Simons + * @author Roman Puchkovskiy */ public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider { @@ -1070,8 +1045,14 @@ public T findAndReplace(Query query, S replacement, FindAndReplaceOptions maybeEmitEvent(new BeforeSaveEvent<>(replacement, mappedReplacement, collectionName)); maybeCallBeforeSave(replacement, mappedReplacement, collectionName); - return doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, + T saved = doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, resultType); + if (saved != null) { + maybeEmitEvent(new AfterSaveEvent<>(saved, mappedReplacement, collectionName)); + return maybeCallAfterSave(saved, mappedReplacement, collectionName); + } + + return saved; } // Find methods that take a Query to express the query and that return a single object that is also removed from the @@ -1233,8 +1214,7 @@ protected T doInsert(String collectionName, T objectToSave, MongoWriter w T saved = populateIdIfNecessary(initialized, id); maybeEmitEvent(new AfterSaveEvent<>(saved, dbDoc, collectionName)); - - return saved; + return maybeCallAfterSave(saved, dbDoc, collectionName); } @Override @@ -1327,8 +1307,9 @@ protected Collection doInsertBatch(String collectionName, Collection(saved, documentList.get(i), collectionName)); - savedObjects.add(saved); + Document doc = documentList.get(i); + maybeEmitEvent(new AfterSaveEvent<>(saved, doc, collectionName)); + savedObjects.add(maybeCallAfterSave(saved, doc, collectionName)); } else { savedObjects.add(obj); } @@ -1398,7 +1379,7 @@ private T doSaveVersioned(AdaptibleEntity source, String collectionName) } maybeEmitEvent(new AfterSaveEvent<>(toSave, mapped.getDocument(), collectionName)); - return toSave; + return maybeCallAfterSave(toSave, mapped.getDocument(), collectionName); } protected T doSave(String collectionName, T objectToSave, MongoWriter writer) { @@ -1419,7 +1400,7 @@ protected T doSave(String collectionName, T objectToSave, MongoWriter wri T saved = populateIdIfNecessary(objectToSave, id); maybeEmitEvent(new AfterSaveEvent<>(saved, dbDoc, collectionName)); - return saved; + return maybeCallAfterSave(saved, dbDoc, collectionName); } @SuppressWarnings("ConstantConditions") @@ -2312,7 +2293,6 @@ protected , T> E maybeEmitEvent(E event) { return event; } - @SuppressWarnings("unchecked") protected T maybeCallBeforeConvert(T object, String collection) { if (null != entityCallbacks) { @@ -2322,7 +2302,6 @@ protected T maybeCallBeforeConvert(T object, String collection) { return object; } - @SuppressWarnings("unchecked") protected T maybeCallBeforeSave(T object, Document document, String collection) { if (null != entityCallbacks) { @@ -2332,6 +2311,24 @@ protected T maybeCallBeforeSave(T object, Document document, String collecti return object; } + protected T maybeCallAfterSave(T object, Document document, String collection) { + + if (null != entityCallbacks) { + return entityCallbacks.callback(AfterSaveCallback.class, object, document, collection); + } + + return object; + } + + protected T maybeCallAfterConvert(T object, Document document, String collection) { + + if (null != entityCallbacks) { + return entityCallbacks.callback(AfterConvertCallback.class, object, document, collection); + } + + return object; + } + /** * Create the specified collection using the provided options * @@ -3101,6 +3098,7 @@ interface DocumentCallback { * * @author Oliver Gierke * @author Christoph Strobl + * @author Roman Puchkovskiy */ @RequiredArgsConstructor private class ReadDocumentCallback implements DocumentCallback { @@ -3110,16 +3108,17 @@ private class ReadDocumentCallback implements DocumentCallback { private final String collectionName; @Nullable - public T doWith(@Nullable Document object) { + public T doWith(@Nullable Document document) { - if (null != object) { - maybeEmitEvent(new AfterLoadEvent<>(object, type, collectionName)); + if (null != document) { + maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); } - T source = reader.read(type, object); + T source = reader.read(type, document); if (null != source) { - maybeEmitEvent(new AfterConvertEvent<>(object, source, collectionName)); + maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); + source = maybeCallAfterConvert(source, document, collectionName); } return source; @@ -3148,24 +3147,25 @@ private class ProjectingReadCallback implements DocumentCallback { */ @SuppressWarnings("unchecked") @Nullable - public T doWith(@Nullable Document object) { + public T doWith(@Nullable Document document) { - if (object == null) { + if (document == null) { return null; } Class typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType : targetType; - if (null != object) { - maybeEmitEvent(new AfterLoadEvent<>(object, targetType, collectionName)); + if (null != document) { + maybeEmitEvent(new AfterLoadEvent<>(document, targetType, collectionName)); } - Object source = reader.read(typeToRead, object); + Object source = reader.read(typeToRead, document); Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; if (null != result) { - maybeEmitEvent(new AfterConvertEvent<>(object, result, collectionName)); + maybeEmitEvent(new AfterConvertEvent<>(document, result, collectionName)); + result = maybeCallAfterConvert(result, document, collectionName); } return (T) result; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index b2f4571324..b65afdb510 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -74,16 +74,7 @@ import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.JsonSchemaMapper; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.convert.MongoConverter; -import org.springframework.data.mongodb.core.convert.MongoCustomConversions; -import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper; -import org.springframework.data.mongodb.core.convert.MongoWriter; -import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; -import org.springframework.data.mongodb.core.convert.QueryMapper; -import org.springframework.data.mongodb.core.convert.UpdateMapper; +import org.springframework.data.mongodb.core.convert.*; import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher; import org.springframework.data.mongodb.core.index.ReactiveIndexOperations; import org.springframework.data.mongodb.core.index.ReactiveMongoPersistentEntityIndexCreator; @@ -91,16 +82,7 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; -import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent; -import org.springframework.data.mongodb.core.mapping.event.AfterDeleteEvent; -import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent; -import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; -import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; -import org.springframework.data.mongodb.core.mapping.event.BeforeDeleteEvent; -import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent; -import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent; -import org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeConvertCallback; -import org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeSaveCallback; +import org.springframework.data.mongodb.core.mapping.event.*; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Meta; @@ -127,16 +109,7 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; -import com.mongodb.client.model.CountOptions; -import com.mongodb.client.model.CreateCollectionOptions; -import com.mongodb.client.model.DeleteOptions; -import com.mongodb.client.model.FindOneAndDeleteOptions; -import com.mongodb.client.model.FindOneAndReplaceOptions; -import com.mongodb.client.model.FindOneAndUpdateOptions; -import com.mongodb.client.model.ReplaceOptions; -import com.mongodb.client.model.ReturnDocument; -import com.mongodb.client.model.UpdateOptions; -import com.mongodb.client.model.ValidationOptions; +import com.mongodb.client.model.*; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertOneResult; @@ -163,6 +136,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Roman Puchkovskiy * @since 2.0 */ public class ReactiveMongoTemplate implements ReactiveMongoOperations, ApplicationContextAware { @@ -1050,7 +1024,7 @@ private Flux aggregateAndMap(MongoCollection collection, List Flux> geoNear(NearQuery near, Class entityClass, S .withOptions(AggregationOptions.builder().collation(near.getCollation()).build()); return aggregate($geoNear, collection, Document.class) // - .map(callback::doWith); + .concatMap(callback::doWith); } /* @@ -1186,9 +1160,13 @@ public Mono findAndReplace(Query query, S replacement, FindAndReplaceO }).flatMap(it -> { PersistableEntityModel flowObject = (PersistableEntityModel) it; - return doFindAndReplace(flowObject.getCollection(), mappedQuery, mappedFields, mappedSort, - queryContext.getCollation(entityType).orElse(null), entityType, flowObject.getTarget(), options, - resultType); + Mono afterFindAndReplace = doFindAndReplace(flowObject.getCollection(), mappedQuery, + mappedFields, mappedSort, queryContext.getCollation(entityType).orElse(null), + entityType, flowObject.getTarget(), options, resultType); + return afterFindAndReplace.flatMap(saved -> { + maybeEmitEvent(new AfterSaveEvent<>(saved, flowObject.getTarget(), flowObject.getCollection())); + return maybeCallAfterSave(saved, flowObject.getTarget(), flowObject.getCollection()); + }); }); } @@ -1345,12 +1323,12 @@ protected Mono doInsert(String collectionName, T objectToSave, MongoWrite }).flatMap(it -> { - return insertDocument(it.getCollection(), it.getTarget(), it.getSource().getClass()).map(id -> { + return insertDocument(it.getCollection(), it.getTarget(), it.getSource().getClass()).flatMap(id -> { T saved = operations.forEntity(it.getSource(), mongoConverter.getConversionService()) .populateIdIfNecessary(id); maybeEmitEvent(new AfterSaveEvent<>(saved, it.getTarget(), collectionName)); - return saved; + return maybeCallAfterSave(saved, it.getTarget(), collectionName); }); }); } @@ -1436,13 +1414,14 @@ protected Flux doInsertBatch(String collectionName, Collection { + return insertDocuments.flatMap(tuple -> { - Object id = MappedDocument.of(tuple.getT2()).getId(); + Document document = tuple.getT2(); + Object id = MappedDocument.of(document).getId(); T saved = tuple.getT1().populateIdIfNecessary(id); - maybeEmitEvent(new AfterSaveEvent<>(saved, tuple.getT2(), collectionName)); - return saved; + maybeEmitEvent(new AfterSaveEvent<>(saved, document, collectionName)); + return maybeCallAfterSave(saved, document, collectionName); }); } @@ -1522,9 +1501,11 @@ private Mono doSaveVersioned(AdaptibleEntity source, String collection maybeEmitEvent(new BeforeSaveEvent<>(toConvert, document, collectionName)); return maybeCallBeforeSave(toConvert, document, collectionName).flatMap(it -> { - return doUpdate(collectionName, query, mapped.updateWithoutId(), it.getClass(), false, false).map(result -> { - return maybeEmitEvent(new AfterSaveEvent(it, document, collectionName)).getSource(); - }); + return doUpdate(collectionName, query, mapped.updateWithoutId(), it.getClass(), false, false) + .flatMap(result -> { + maybeEmitEvent(new AfterSaveEvent(it, document, collectionName)); + return maybeCallAfterSave(it, document, collectionName); + }); }); }); }); @@ -1546,10 +1527,11 @@ protected Mono doSave(String collectionName, T objectToSave, MongoWriter< return maybeCallBeforeSave(toConvert, dbDoc, collectionName).flatMap(it -> { - return saveDocument(collectionName, dbDoc, it.getClass()).map(id -> { + return saveDocument(collectionName, dbDoc, it.getClass()).flatMap(id -> { T saved = entity.populateIdIfNecessary(id); - return maybeEmitEvent(new AfterSaveEvent<>(saved, dbDoc, collectionName)).getSource(); + maybeEmitEvent(new AfterSaveEvent<>(saved, dbDoc, collectionName)); + return maybeCallAfterSave(saved, dbDoc, collectionName); }); }); }); @@ -2213,7 +2195,7 @@ public Flux mapReduce(Query filterQuery, Class domainType, String inpu publisher = collation.map(Collation::toMongoCollation).map(publisher::collation).orElse(publisher); return Flux.from(publisher) - .map(new ReadDocumentCallback<>(mongoConverter, resultType, inputCollectionName)::doWith); + .concatMap(new ReadDocumentCallback<>(mongoConverter, resultType, inputCollectionName)::doWith); }); } @@ -2613,7 +2595,6 @@ protected , T> E maybeEmitEvent(E event) { return event; } - @SuppressWarnings("unchecked") protected Mono maybeCallBeforeConvert(T object, String collection) { if (null != entityCallbacks) { @@ -2623,7 +2604,6 @@ protected Mono maybeCallBeforeConvert(T object, String collection) { return Mono.just(object); } - @SuppressWarnings("unchecked") protected Mono maybeCallBeforeSave(T object, Document document, String collection) { if (null != entityCallbacks) { @@ -2633,6 +2613,24 @@ protected Mono maybeCallBeforeSave(T object, Document document, String co return Mono.just(object); } + protected Mono maybeCallAfterSave(T object, Document document, String collection) { + + if (null != entityCallbacks) { + return entityCallbacks.callback(ReactiveAfterSaveCallback.class, object, document, collection); + } + + return Mono.just(object); + } + + protected Mono maybeCallAfterConvert(T object, Document document, String collection) { + + if (null != entityCallbacks) { + return entityCallbacks.callback(ReactiveAfterConvertCallback.class, object, document, collection); + } + + return Mono.just(object); + } + private MongoCollection getAndPrepareCollection(MongoDatabase db, String collectionName) { try { @@ -2720,7 +2718,7 @@ private Mono executeFindOneInternal(ReactiveCollectionCallback DocumentCallback objectCallback, String collectionName) { return createMono(collectionName, - collection -> Mono.from(collectionCallback.doInCollection(collection)).map(objectCallback::doWith)); + collection -> Mono.from(collectionCallback.doInCollection(collection)).flatMap(objectCallback::doWith)); } /** @@ -2746,7 +2744,7 @@ private Flux executeFindMultiInternal(ReactiveCollectionQueryCallback { return Flux.from(preparer.initiateFind(collection, collectionCallback::doInCollection)) - .map(objectCallback::doWith); + .concatMap(objectCallback::doWith); }); } @@ -3042,7 +3040,7 @@ private static FindOneAndDeleteOptions convertToFindOneAndDeleteOptions(Document interface DocumentCallback { - T doWith(Document object); + Mono doWith(Document object); } /** @@ -3071,6 +3069,7 @@ interface ReactiveCollectionQueryCallback extends ReactiveCollectionCallback< * {@link EntityReader}. * * @author Mark Paluch + * @author Roman Puchkovskiy */ class ReadDocumentCallback implements DocumentCallback { @@ -3088,27 +3087,33 @@ class ReadDocumentCallback implements DocumentCallback { this.collectionName = collectionName; } - public T doWith(@Nullable Document object) { + public Mono doWith(Document document) { - if (null != object) { - maybeEmitEvent(new AfterLoadEvent<>(object, type, collectionName)); - } - T source = reader.read(type, object); + maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); + + T source = reader.read(type, document); if (null != source) { - maybeEmitEvent(new AfterConvertEvent<>(object, source, collectionName)); + maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); } - return source; + return Mono.defer(() -> { + if (null != source) { + return maybeCallAfterConvert(source, document, collectionName); + } else { + return Mono.empty(); + } + }); } } /** - * {@link MongoTemplate.DocumentCallback} transforming {@link Document} into the given {@code targetType} or + * {@link DocumentCallback} transforming {@link Document} into the given {@code targetType} or * decorating the {@code sourceType} with a {@literal projection} in case the {@code targetType} is an - * {@litera interface}. + * {@literal interface}. * * @param * @param * @author Christoph Strobl + * @author Roman Puchkovskiy * @since 2.0 */ @RequiredArgsConstructor @@ -3119,29 +3124,30 @@ private class ProjectingReadCallback implements DocumentCallback { private final @NonNull Class targetType; private final @NonNull String collectionName; - @Nullable @SuppressWarnings("unchecked") - public T doWith(@Nullable Document object) { - - if (object == null) { - return null; - } + public Mono doWith(Document document) { Class typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) // ? entityType // : targetType; - if (null != object) { - maybeEmitEvent(new AfterLoadEvent<>(object, typeToRead, collectionName)); - } + maybeEmitEvent(new AfterLoadEvent<>(document, typeToRead, collectionName)); - Object source = reader.read(typeToRead, object); + Object source = reader.read(typeToRead, document); Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; - if (null != source) { - maybeEmitEvent(new AfterConvertEvent<>(object, result, collectionName)); + T castEntity = (T) result; + if (null != castEntity) { + maybeEmitEvent(new AfterConvertEvent<>(document, castEntity, collectionName)); } - return (T) result; + + return Mono.defer(() -> { + if (null != castEntity) { + return maybeCallAfterConvert(castEntity, document, collectionName); + } else { + return Mono.empty(); + } + }); } } @@ -3151,6 +3157,7 @@ public T doWith(@Nullable Document object) { * * @author Mark Paluch * @author Chrstoph Strobl + * @author Roman Puchkovskiy */ static class GeoNearResultDocumentCallback implements DocumentCallback> { @@ -3175,16 +3182,17 @@ static class GeoNearResultDocumentCallback implements DocumentCallback doWith(Document object) { + public Mono> doWith(Document object) { - double distance = Double.NaN; + final double distance; if (object.containsKey(distanceField)) { distance = NumberUtils.convertNumberToTargetClass(object.get(distanceField, Number.class), Double.class); + } else { + distance = Double.NaN; } - - T doWith = delegate.doWith(object); - - return new GeoResult<>(doWith, new Distance(distance, metric)); + + return delegate.doWith(object) + .map(doWith -> new GeoResult<>(doWith, new Distance(distance, metric))); } } @@ -3202,7 +3210,6 @@ class QueryFindPublisherPreparer implements FindPublisherPreparer { this.type = type; } - @SuppressWarnings("deprecation") public FindPublisher prepare(FindPublisher findPublisher) { FindPublisher findPublisherToUse = operations.forType(type) // 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 6dfb990bff..51306aec42 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 @@ -50,6 +50,7 @@ import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PreferredConstructor; import org.springframework.data.mapping.PreferredConstructor.Parameter; +import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.ConvertingPropertyAccessor; import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator; @@ -64,6 +65,7 @@ import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback; import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent; import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent; import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent; @@ -91,6 +93,7 @@ * @author Christoph Strobl * @author Jordi Llach * @author Mark Paluch + * @author Roman Puchkovskiy */ public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware { @@ -110,6 +113,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App protected @Nullable CodecRegistryProvider codecRegistryProvider; private SpELContext spELContext; + private @Nullable EntityCallbacks entityCallbacks; /** * Creates a new {@link MappingMongoConverter} given the new {@link DbRefResolver} and {@link MappingContext}. @@ -212,6 +216,26 @@ public void setApplicationContext(ApplicationContext applicationContext) throws this.applicationContext = applicationContext; this.spELContext = new SpELContext(this.spELContext, applicationContext); + + if (entityCallbacks == null) { + setEntityCallbacks(EntityCallbacks.create(applicationContext)); + } + } + + /** + * Set the {@link EntityCallbacks} instance to use when invoking + * {@link org.springframework.data.mapping.callback.EntityCallback callbacks} like the {@link AfterConvertCallback}. + *

      + * Overrides potentially existing {@link EntityCallbacks}. + * + * @param entityCallbacks must not be {@literal null}. + * @throws IllegalArgumentException if the given instance is {@literal null}. + * @since 3.0 + */ + public void setEntityCallbacks(EntityCallbacks entityCallbacks) { + + Assert.notNull(entityCallbacks, "EntityCallbacks must not be null!"); + this.entityCallbacks = entityCallbacks; } /* @@ -1605,7 +1629,7 @@ private List bulkReadAndConvertDBRefs(List dbrefs, TypeInformation : bulkReadRefs(dbrefs); String collectionName = dbrefs.iterator().next().getCollectionName(); - List targeList = new ArrayList<>(dbrefs.size()); + List targetList = new ArrayList<>(dbrefs.size()); for (Document document : referencedRawDocuments) { @@ -1613,15 +1637,17 @@ private List bulkReadAndConvertDBRefs(List dbrefs, TypeInformation maybeEmitEvent(new AfterLoadEvent<>(document, (Class) rawType, collectionName)); } - final T target = (T) read(type, document, path); - targeList.add(target); + T target = (T) read(type, document, path); if (target != null) { maybeEmitEvent(new AfterConvertEvent<>(document, target, collectionName)); + target = maybeCallAfterConvert(target, document, collectionName); } + + targetList.add(target); } - return targeList; + return targetList; } private void maybeEmitEvent(MongoMappingEvent event) { @@ -1635,6 +1661,15 @@ private boolean canPublishEvent() { return this.applicationContext != null; } + protected T maybeCallAfterConvert(T object, Document document, String collection) { + + if (null != entityCallbacks) { + return entityCallbacks.callback(AfterConvertCallback.class, object, document, collection); + } + + return object; + } + /** * Performs the fetch operation for the given {@link DBRef}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java new file mode 100644 index 0000000000..3dc4f04176 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping.event; + +import org.bson.Document; +import org.springframework.data.mapping.callback.EntityCallback; + +/** + * Callback being invoked after a domain object is converted from a Document (when reading from the DB). + * + * @author Roman Puchkovskiy + * @since 3.0 + */ +@FunctionalInterface +public interface AfterConvertCallback extends EntityCallback { + + /** + * Entity callback method invoked after a domain object is converted from a Document. Can return either the same + * or a modified instance of the domain object. + * + * @param entity the domain object (the result of the conversion). + * @param document must not be {@literal null}. + * @param collection name of the collection. + * @return the domain object that is the result of the conversion from the Document. + */ + T onAfterConvert(T entity, Document document, String collection); +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java new file mode 100644 index 0000000000..c22597ca49 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping.event; + +import org.bson.Document; +import org.springframework.data.mapping.callback.EntityCallback; + +/** + * Entity callback triggered after save of a document. + * + * @author Roman Puchkovskiy + * @since 3.0 + */ +@FunctionalInterface +public interface AfterSaveCallback extends EntityCallback { + + /** + * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance + * of the domain object. + * + * @param entity the domain object that was saved. + * @param document {@link Document} representing the {@code entity}. + * @param collection name of the collection. + * @return the domain object that was persisted. + */ + T onAfterSave(T entity, Document document, String collection); +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java new file mode 100644 index 0000000000..7a273cf153 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java @@ -0,0 +1,43 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping.event; + +import org.bson.Document; +import org.reactivestreams.Publisher; +import org.springframework.data.mapping.callback.EntityCallback; +import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; + +/** + * Callback being invoked after a domain object is converted from a Document (when reading from the DB). + * + * @author Roman Puchkovskiy + * @since 3.0 + * @see ReactiveEntityCallbacks + */ +@FunctionalInterface +public interface ReactiveAfterConvertCallback extends EntityCallback { + + /** + * Entity callback method invoked after a domain object is converted from a Document. Can return either the same + * or a modified instance of the domain object. + * + * @param entity the domain object (the result of the conversion). + * @param document must not be {@literal null}. + * @param collection name of the collection. + * @return a {@link Publisher} emitting the domain object that is the result of the conversion from the Document. + */ + Publisher onAfterConvert(T entity, Document document, String collection); +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java new file mode 100644 index 0000000000..64eda738ff --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java @@ -0,0 +1,44 @@ +/* + * Copyright 2020 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 + * + * https://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.mapping.event; + +import org.bson.Document; +import org.reactivestreams.Publisher; + +import org.springframework.data.mapping.callback.EntityCallback; +import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; + +/** + * Entity callback triggered after save of a document. + * + * @author Roman Puchkovskiy + * @since 3.0 + * @see ReactiveEntityCallbacks + */ +@FunctionalInterface +public interface ReactiveAfterSaveCallback extends EntityCallback { + + /** + * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance + * of the domain object. + * + * @param entity the domain object that was saved. + * @param document {@link Document} representing the {@code entity}. + * @param collection name of the collection. + * @return a {@link Publisher} emitting the domain object to be returned to the caller. + */ + Publisher onAfterSave(T entity, Document document, String collection); +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 47302d2ac8..48682071d3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -54,6 +54,7 @@ import org.springframework.data.mongodb.core.convert.UpdateMapper; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveCallback; import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; @@ -84,6 +85,7 @@ * @author Mark Paluch * @author Minsu Kim * @author Jens Schauder + * @author Roman Puchkovskiy */ @ExtendWith(MockitoExtension.class) class DefaultBulkOperationsUnitTests { @@ -208,16 +210,17 @@ void bulkReplaceOneShouldMapQueryCorrectly() { assertThat(updateModel.getReplacement().getString("lastName")).isEqualTo("Kim"); } - @Test // DATAMONGO-2261 + @Test // DATAMONGO-2261, DATAMONGO-2479 void bulkInsertInvokesEntityCallbacks() { BeforeConvertPersonCallback beforeConvertCallback = spy(new BeforeConvertPersonCallback()); BeforeSavePersonCallback beforeSaveCallback = spy(new BeforeSavePersonCallback()); + AfterSavePersonCallback afterSaveCallback = spy(new AfterSavePersonCallback()); ops = new DefaultBulkOperations(template, "collection-1", new BulkOperationContext(BulkMode.ORDERED, Optional.of(mappingContext.getPersistentEntity(Person.class)), new QueryMapper(converter), new UpdateMapper(converter), null, - EntityCallbacks.create(beforeConvertCallback, beforeSaveCallback))); + EntityCallbacks.create(beforeConvertCallback, beforeSaveCallback, afterSaveCallback))); Person entity = new Person("init"); ops.insert(entity); @@ -229,11 +232,13 @@ void bulkInsertInvokesEntityCallbacks() { ops.execute(); verify(beforeSaveCallback).onBeforeSave(personArgumentCaptor.capture(), any(), eq("collection-1")); - assertThat(personArgumentCaptor.getAllValues()).extracting("firstName").containsExactly("init", "before-convert"); + verify(afterSaveCallback).onAfterSave(personArgumentCaptor.capture(), any(), eq("collection-1")); + assertThat(personArgumentCaptor.getAllValues()).extracting("firstName") + .containsExactly("init", "before-convert", "before-convert"); verify(collection).bulkWrite(captor.capture(), any()); InsertOneModel updateModel = (InsertOneModel) captor.getValue().get(0); - assertThat(updateModel.getDocument()).containsEntry("firstName", "before-save"); + assertThat(updateModel.getDocument()).containsEntry("firstName", "after-save"); } @Test // DATAMONGO-2290 @@ -365,6 +370,16 @@ public Person onBeforeSave(Person entity, Document document, String collection) } } + static class AfterSavePersonCallback implements AfterSaveCallback { + + @Override + public Person onAfterSave(Person entity, Document document, String collection) { + + document.put("firstName", "after-save"); + return new Person("after-save"); + } + } + static class NullExceptionTranslator implements PersistenceExceptionTranslator { @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 3d87afad8b..5539f53916 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -25,7 +25,9 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -37,6 +39,7 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -81,6 +84,9 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; +import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveCallback; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeSaveCallback; @@ -97,10 +103,13 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; +import com.google.common.collect.ImmutableMap; import com.mongodb.MongoClientSettings; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.ReadPreference; +import com.mongodb.ServerAddress; +import com.mongodb.ServerCursor; import com.mongodb.WriteConcern; import com.mongodb.client.AggregateIterable; import com.mongodb.client.DistinctIterable; @@ -129,6 +138,7 @@ * @author Christoph Strobl * @author Mark Paluch * @author Michael J. Simons + * @author Roman Puchkovskiy */ @MockitoSettings(strictness = Strictness.LENIENT) public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @@ -1921,6 +1931,241 @@ void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { verify(findIterable).projection(new Document("country", 1).append("userid", 1)); } + @Test // DATAMONGO-2479 + public void findShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(findIterable.iterator()).thenReturn(new OneElementCursor<>(document)); + + template.find(new Query(), Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + private Document initialLukeDocument() { + return new Document(ImmutableMap.of( + "_id", "init", + "firstname", "luke" + )); + } + + private Person initialLuke() { + Person expectedEnitty = new Person(); + expectedEnitty.id = "init"; + expectedEnitty.firstname = "luke"; + return expectedEnitty; + } + + @Test // DATAMONGO-2479 + public void findByIdShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(findIterable.first()).thenReturn(document); + + template.findById("init", Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + @Test // DATAMONGO-2479 + public void findOneShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(findIterable.first()).thenReturn(document); + + template.findOne(new Query(), Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + @Test // DATAMONGO-2479 + public void findAllShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(findIterable.iterator()).thenReturn(new OneElementCursor<>(document)); + + template.findAll(Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + @Test // DATAMONGO-2479 + public void findAndModifyShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(document); + + template.findAndModify(new Query(), new Update(), Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + @Test // DATAMONGO-2479 + public void findAndRemoveShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(document); + + template.findAndRemove(new Query(), Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + @Test // DATAMONGO-2479 + public void findAllAndRemoveShouldInvokeAfterConvertCallback() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(findIterable.iterator()).thenReturn(new OneElementCursor<>(document)); + + template.findAllAndRemove(new Query(), Person.class); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + } + + @Test // DATAMONGO-2479 + public void findAndReplaceShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + Person entity = initialLuke(); + + Document document = initialLukeDocument(); + when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(document); + + Person saved = template.findAndReplace(new Query(), entity); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(saved.id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void saveShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + + Person entity = initialLuke(); + + Person saved = template.save(entity); + + verify(afterSaveCallback).onAfterSave(eq(entity), any(), anyString()); + assertThat(saved.id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void insertShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + + Person entity = initialLuke(); + + Person saved = template.insert(entity); + + verify(afterSaveCallback).onAfterSave(eq(entity), any(), anyString()); + assertThat(saved.id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void insertAllShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + + Person entity1 = new Person(); + entity1.id = "1"; + entity1.firstname = "luke"; + + Person entity2 = new Person(); + entity1.id = "2"; + entity1.firstname = "luke"; + + Collection saved = template.insertAll(Arrays.asList(entity1, entity2)); + + verify(afterSaveCallback, times(2)).onAfterSave(any(), any(), anyString()); + assertThat(saved.iterator().next().getId()).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void findAndReplaceShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + + Person entity = initialLuke(); + + Document document = initialLukeDocument(); + when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(document); + + Person saved = template.findAndReplace(new Query(), entity); + + verify(afterSaveCallback).onAfterSave(eq(initialLuke()), any(), anyString()); + assertThat(saved.id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void findAndReplaceShouldEmitAfterSaveEvent() { + + AbstractMongoEventListener eventListener = new AbstractMongoEventListener() { + + @Override + public void onAfterSave(AfterSaveEvent event) { + + assertThat(event.getSource().id).isEqualTo("init"); + event.getSource().id = "after-save-event"; + } + }; + + StaticApplicationContext ctx = new StaticApplicationContext(); + ctx.registerBean(ApplicationListener.class, () -> eventListener); + ctx.refresh(); + + template.setApplicationContext(ctx); + + Person entity = initialLuke(); + + Document document = initialLukeDocument(); + when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(document); + + Person saved = template.findAndReplace(new Query(), entity); + + assertThat(saved.id).isEqualTo("after-save-event"); + } + class AutogenerateableId { @Id BigInteger id; @@ -2097,4 +2342,74 @@ public Person onBeforeSave(Person entity, Document document, String collection) return entity; } } + + static class ValueCapturingAfterSaveCallback extends ValueCapturingEntityCallback + implements AfterSaveCallback { + + @Override + public Person onAfterSave(Person entity, Document document, String collection) { + + capture(entity); + return new Person() {{ + id = "after-save"; + firstname = entity.firstname; + }}; + } + } + + static class ValueCapturingAfterConvertCallback extends ValueCapturingEntityCallback + implements AfterConvertCallback { + + @Override + public Person onAfterConvert(Person entity, Document document, String collection) { + + capture(entity); + return new Person() {{ + id = "after-convert"; + firstname = entity.firstname; + }}; + } + } + + static class OneElementCursor implements MongoCursor { + private final Iterator iterator; + + OneElementCursor(T element) { + iterator = Collections.singletonList(element).iterator(); + } + + @Override + public void close() { + // nothing to close + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + return iterator.next(); + } + + @Override + public T tryNext() { + if (iterator.hasNext()) { + return iterator.next(); + } else { + return null; + } + } + + @Override + public ServerCursor getServerCursor() { + throw new IllegalStateException("Not implemented"); + } + + @Override + public ServerAddress getServerAddress() { + throw new IllegalStateException("Not implemented"); + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index e34f4922cc..f95c5fe67d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -21,6 +21,7 @@ import static org.springframework.data.mongodb.test.util.Assertions.assertThat; import lombok.Data; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -32,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.assertj.core.api.Assertions; import org.bson.Document; @@ -46,9 +48,11 @@ import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; import org.springframework.context.support.StaticApplicationContext; import org.springframework.data.annotation.Id; import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; @@ -65,6 +69,10 @@ import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; +import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; +import org.springframework.data.mongodb.core.mapping.event.ReactiveAfterConvertCallback; +import org.springframework.data.mongodb.core.mapping.event.ReactiveAfterSaveCallback; import org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeConvertCallback; import org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeSaveCallback; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; @@ -78,6 +86,7 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; +import com.google.common.collect.ImmutableMap; import com.mongodb.MongoClientSettings; import com.mongodb.ReadPreference; import com.mongodb.client.model.CountOptions; @@ -88,6 +97,9 @@ import com.mongodb.client.model.FindOneAndUpdateOptions; import com.mongodb.client.model.ReplaceOptions; import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.result.DeleteResult; +import com.mongodb.client.result.InsertManyResult; +import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; import com.mongodb.reactivestreams.client.AggregatePublisher; import com.mongodb.reactivestreams.client.DistinctPublisher; @@ -102,6 +114,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Roman Puchkovskiy */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -1096,6 +1109,286 @@ void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { verify(findPublisher).projection(new Document("country", 1).append("userid", 1)); } + @Test // DATAMONGO-2479 + public void findShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.find(Document.class)).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + + List results = template.find(new Query(), Person.class).timeout(Duration.ofSeconds(1)) + .toStream().collect(Collectors.toList()); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(results.get(0).id).isEqualTo("after-convert"); + } + + private Document initialLukeDocument() { + return new Document(ImmutableMap.of( + "_id", "init", + "firstname", "luke" + )); + } + + private Person initialLuke() { + Person expectedEnitty = new Person(); + expectedEnitty.id = "init"; + expectedEnitty.firstname = "luke"; + return expectedEnitty; + } + + @Test // DATAMONGO-2479 + public void findByIdShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + + Person result = template.findById("init", Person.class).block(Duration.ofSeconds(1)); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(result.id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void findOneShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + + Person result = template.findOne(new Query(), Person.class).block(Duration.ofSeconds(1)); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(result.id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void findAllShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.find(Document.class)).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + + List results = template.findAll(Person.class).timeout(Duration.ofSeconds(1)) + .toStream().collect(Collectors.toList()); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(results.get(0).id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void findAndModifyShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + + Person result = template.findAndModify(new Query(), new Update(), Person.class).block(Duration.ofSeconds(1)); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(result.id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void findAndRemoveShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + + Person result = template.findAndRemove(new Query(), Person.class).block(Duration.ofSeconds(1)); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(result.id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void findAllAndRemoveShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + Document document = initialLukeDocument(); + when(collection.find(Document.class)).thenReturn(findPublisher); + makeFindPublisherPublishJust(document); + when(collection.deleteMany(any(Bson.class), any(DeleteOptions.class))) + .thenReturn(Mono.just(spy(DeleteResult.class))); + + List results = template.findAllAndRemove(new Query(), Person.class).timeout(Duration.ofSeconds(1)) + .toStream().collect(Collectors.toList()); + + verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + assertThat(results.get(0).id).isEqualTo("after-convert"); + } + + private void makeFindPublisherPublishJust(Document document) { + + Publisher realPublisher = Flux.just(document); + + doAnswer(invocation -> { + Subscriber subscriber = invocation.getArgument(0); + realPublisher.subscribe(subscriber); + return null; + }).when(findPublisher).subscribe(any()); + } + + @Test // DATAMONGO-2479 + public void findAndReplaceShouldInvokeAfterConvertCallbacks() { + + ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); + + when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher); + makeFindPublisherPublishJust(initialLukeDocument()); + + Person entity = new Person(); + entity.id = "init"; + entity.firstname = "luke"; + + Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); + + verify(afterConvertCallback).onAfterConvert(eq(entity), any(), anyString()); + assertThat(saved.id).isEqualTo("after-convert"); + } + + @Test // DATAMONGO-2479 + public void saveShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); + + when(collection.replaceOne(any(Bson.class), any(Document.class), any(ReplaceOptions.class))) + .thenReturn(Mono.just(mock(UpdateResult.class))); + + Person entity = initialLuke(); + + Person saved = template.save(entity).block(Duration.ofSeconds(1)); + + verify(afterSaveCallback).onAfterSave(eq(entity), any(), anyString()); + assertThat(saved.id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void insertShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); + + when(collection.insertOne(any())).thenReturn(Mono.just(mock(InsertOneResult.class))); + + Person entity = initialLuke(); + + Person saved = template.insert(entity).block(Duration.ofSeconds(1)); + + verify(afterSaveCallback).onAfterSave(eq(entity), any(), anyString()); + assertThat(saved.id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void insertAllShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); + + Person entity1 = new Person(); + entity1.id = "1"; + entity1.firstname = "luke"; + + Person entity2 = new Person(); + entity1.id = "2"; + entity1.firstname = "luke"; + + when(collection.insertMany(anyList())).then(invocation -> { + List list = invocation.getArgument(0); + return Flux.fromIterable(list).map(i -> mock(InsertManyResult.class)); + }); + + List saved = template.insertAll(Arrays.asList(entity1, entity2)) + .timeout(Duration.ofSeconds(1)) + .toStream().collect(Collectors.toList()); + + verify(afterSaveCallback, times(2)).onAfterSave(any(), any(), anyString()); + assertThat(saved.get(0).id).isEqualTo("after-save"); + assertThat(saved.get(1).id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void findAndReplaceShouldInvokeAfterSaveCallbacks() { + + ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); + + when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher); + makeFindPublisherPublishJust(initialLukeDocument()); + + Person entity = initialLuke(); + + Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); + + verify(afterSaveCallback).onAfterSave(eq(entity), any(), anyString()); + assertThat(saved.id).isEqualTo("after-save"); + } + + @Test // DATAMONGO-2479 + public void findAndReplaceShouldEmitAfterSaveEvent() { + + AbstractMongoEventListener eventListener = new AbstractMongoEventListener() { + + @Override + public void onAfterSave(AfterSaveEvent event) { + + assertThat(event.getSource().id).isEqualTo("init"); + event.getSource().id = "after-save-event"; + } + }; + + StaticApplicationContext ctx = new StaticApplicationContext(); + ctx.registerBean(ApplicationListener.class, () -> eventListener); + ctx.refresh(); + + template.setApplicationContext(ctx); + + Person entity = initialLuke(); + + Document document = initialLukeDocument(); + when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(Mono.just(document)); + + Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); + + assertThat(saved.id).isEqualTo("after-save-event"); + } + @Data @org.springframework.data.mongodb.core.mapping.Document(collection = "star-wars") static class Person { @@ -1179,4 +1472,33 @@ public Mono onBeforeSave(Person entity, Document document, String collec return Mono.just(entity); } } + + static class ValueCapturingAfterConvertCallback extends ValueCapturingEntityCallback + implements ReactiveAfterConvertCallback { + + @Override + public Mono onAfterConvert(Person entity, Document document, String collection) { + + capture(entity); + return Mono.just(new Person() {{ + id = "after-convert"; + firstname = entity.firstname; + }}); + } + } + + static class ValueCapturingAfterSaveCallback extends ValueCapturingEntityCallback + implements ReactiveAfterSaveCallback { + + @Override + public Mono onAfterSave(Person entity, Document document, String collection) { + + capture(entity); + return Mono.just(new Person() {{ + id = "after-save"; + firstname = entity.firstname; + }}); + } + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index c2af8c856d..cdc0a02b43 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -30,6 +30,7 @@ import java.time.temporal.ChronoUnit; import java.util.*; +import org.assertj.core.api.Assertions; import org.bson.types.Code; import org.bson.types.Decimal128; import org.bson.types.ObjectId; @@ -46,6 +47,7 @@ import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; +import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; @@ -62,6 +64,7 @@ import org.springframework.data.geo.Polygon; import org.springframework.data.geo.Shape; import org.springframework.data.mapping.MappingException; +import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.model.MappingInstantiationException; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.convert.DocumentAccessorUnitTests.NestedType; @@ -75,6 +78,7 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.PersonPojoStringId; import org.springframework.data.mongodb.core.mapping.TextScore; +import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback; import org.springframework.data.util.ClassTypeInformation; import org.springframework.test.util.ReflectionTestUtils; @@ -90,6 +94,7 @@ * @author Patrik Wasik * @author Christoph Strobl * @author Mark Paluch + * @author Roman Puchkovskiy */ @ExtendWith(MockitoExtension.class) public class MappingMongoConverterUnitTests { @@ -2103,6 +2108,62 @@ void shouldAllowReadingBackDbObject() { .isEqualTo(new BasicDBObject("property", "value")); } + @Test // DATAMONGO-2479 + public void entityCallbacksAreNotSetByDefault() { + Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isNull(); + } + + @Test // DATAMONGO-2479 + public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { + + ApplicationContext ctx = new StaticApplicationContext(); + converter.setApplicationContext(ctx); + + Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isNotNull(); + } + + @Test // DATAMONGO-2479 + public void setterForEntityCallbackOverridesContextInitializedOnes() { + + ApplicationContext ctx = new StaticApplicationContext(); + converter.setApplicationContext(ctx); + + EntityCallbacks callbacks = EntityCallbacks.create(); + converter.setEntityCallbacks(callbacks); + + Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isSameAs(callbacks); + } + + @Test // DATAMONGO-2479 + public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { + + EntityCallbacks callbacks = EntityCallbacks.create(); + ApplicationContext ctx = new StaticApplicationContext(); + + converter.setEntityCallbacks(callbacks); + converter.setApplicationContext(ctx); + + Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isSameAs(callbacks); + } + + @Test // DATAMONGO-2479 + public void resolveDBRefMapValueShouldInvokeCallbacks() { + + AfterConvertCallback afterConvertCallback = spy(new ReturningAfterConvertCallback()); + converter.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + + when(resolver.fetch(Mockito.any(DBRef.class))).thenReturn(new org.bson.Document()); + DBRef dbRef = mock(DBRef.class); + + org.bson.Document refMap = new org.bson.Document("foo", dbRef); + org.bson.Document document = new org.bson.Document("personMap", refMap); + + DBRefWrapper result = converter.read(DBRefWrapper.class, document); + + verify(afterConvertCallback).onAfterConvert(eq(result.personMap.get("foo")), + eq(new org.bson.Document()), any()); + } + static class GenericType { T content; } @@ -2565,4 +2626,12 @@ static class WithExplicitTargetTypes { Date dateAsObjectId; } + static class ReturningAfterConvertCallback implements AfterConvertCallback { + + @Override + public Person onAfterConvert(Person entity, org.bson.Document document, String collection) { + + return entity; + } + } } From 4f0dc04a810ff866ff2e66bb53a27ff7e107b712 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 16 Mar 2020 11:27:25 +0100 Subject: [PATCH 0108/1381] DATAMONGO-2479 - Polishing. Tweak Javadoc. Update reference documentation. Slightly refactor reactive flows to reduce operator count. Simplify test fixtures and remove Google Guava usage. Reformat code. Original pull request: #839. --- .../mongodb/core/DefaultBulkOperations.java | 47 +-- .../data/mongodb/core/MongoTemplate.java | 43 +- .../mongodb/core/ReactiveMongoTemplate.java | 128 +++--- .../mapping/event/AfterConvertCallback.java | 10 +- .../core/mapping/event/AfterSaveCallback.java | 6 +- .../mapping/event/BeforeConvertCallback.java | 1 + .../mapping/event/BeforeSaveCallback.java | 1 + .../event/ReactiveAfterConvertCallback.java | 13 +- .../event/ReactiveAfterSaveCallback.java | 6 +- .../event/ReactiveBeforeConvertCallback.java | 3 +- .../event/ReactiveBeforeSaveCallback.java | 3 +- .../mongodb/core/MongoTemplateUnitTests.java | 386 +++++++++--------- .../core/ReactiveMongoTemplateUnitTests.java | 310 +++++++------- .../reference/mongo-entity-callbacks.adoc | 12 + 14 files changed, 501 insertions(+), 468 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index 9c553f2777..bbd99d3d8d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -424,51 +424,52 @@ private void addModel(Object source, WriteModel model) { models.add(new SourceAwareWriteModelHolder(source, model)); } - private void maybeEmitBeforeSaveEvent(SourceAwareWriteModelHolder it) { + private void maybeEmitBeforeSaveEvent(SourceAwareWriteModelHolder holder) { - if (it.getModel() instanceof InsertOneModel) { + if (holder.getModel() instanceof InsertOneModel) { - Document target = ((InsertOneModel) it.getModel()).getDocument(); - maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), target, collectionName)); - } else if (it.getModel() instanceof ReplaceOneModel) { + Document target = ((InsertOneModel) holder.getModel()).getDocument(); + maybeEmitEvent(new BeforeSaveEvent<>(holder.getSource(), target, collectionName)); + } else if (holder.getModel() instanceof ReplaceOneModel) { - Document target = ((ReplaceOneModel) it.getModel()).getReplacement(); - maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), target, collectionName)); + Document target = ((ReplaceOneModel) holder.getModel()).getReplacement(); + maybeEmitEvent(new BeforeSaveEvent<>(holder.getSource(), target, collectionName)); } } - private void maybeEmitAfterSaveEvent(SourceAwareWriteModelHolder it) { + private void maybeEmitAfterSaveEvent(SourceAwareWriteModelHolder holder) { - if (it.getModel() instanceof InsertOneModel) { + if (holder.getModel() instanceof InsertOneModel) { - Document target = ((InsertOneModel) it.getModel()).getDocument(); - maybeEmitEvent(new AfterSaveEvent<>(it.getSource(), target, collectionName)); - } else if (it.getModel() instanceof ReplaceOneModel) { + Document target = ((InsertOneModel) holder.getModel()).getDocument(); + maybeEmitEvent(new AfterSaveEvent<>(holder.getSource(), target, collectionName)); + } else if (holder.getModel() instanceof ReplaceOneModel) { - Document target = ((ReplaceOneModel) it.getModel()).getReplacement(); - maybeEmitEvent(new AfterSaveEvent<>(it.getSource(), target, collectionName)); + Document target = ((ReplaceOneModel) holder.getModel()).getReplacement(); + maybeEmitEvent(new AfterSaveEvent<>(holder.getSource(), target, collectionName)); } } - private void maybeInvokeAfterSaveCallback(SourceAwareWriteModelHolder it) { + private void maybeInvokeAfterSaveCallback(SourceAwareWriteModelHolder holder) { - if (it.getModel() instanceof InsertOneModel) { + if (holder.getModel() instanceof InsertOneModel) { - Document target = ((InsertOneModel) it.getModel()).getDocument(); - maybeInvokeAfterSaveCallback(it.getSource(), target); - } else if (it.getModel() instanceof ReplaceOneModel) { + Document target = ((InsertOneModel) holder.getModel()).getDocument(); + maybeInvokeAfterSaveCallback(holder.getSource(), target); + } else if (holder.getModel() instanceof ReplaceOneModel) { - Document target = ((ReplaceOneModel) it.getModel()).getReplacement(); - maybeInvokeAfterSaveCallback(it.getSource(), target); + Document target = ((ReplaceOneModel) holder.getModel()).getReplacement(); + maybeInvokeAfterSaveCallback(holder.getSource(), target); } } private , T> E maybeEmitEvent(E event) { - if (null != bulkOperationContext.getEventPublisher()) { - bulkOperationContext.getEventPublisher().publishEvent(event); + if (bulkOperationContext.getEventPublisher() == null) { + return event; } + bulkOperationContext.getEventPublisher().publishEvent(event); return event; } 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 20055ebbff..332ec87e85 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 @@ -71,7 +71,16 @@ import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; -import org.springframework.data.mongodb.core.convert.*; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; +import org.springframework.data.mongodb.core.convert.JsonSchemaMapper; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper; +import org.springframework.data.mongodb.core.convert.MongoWriter; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.convert.UpdateMapper; import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.index.IndexOperationsProvider; import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher; @@ -111,7 +120,16 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; -import com.mongodb.client.*; +import com.mongodb.client.AggregateIterable; +import com.mongodb.client.ClientSession; +import com.mongodb.client.DistinctIterable; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MapReduceIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.MongoIterable; import com.mongodb.client.model.*; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; @@ -1047,6 +1065,7 @@ public T findAndReplace(Query query, S replacement, FindAndReplaceOptions T saved = doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, resultType); + if (saved != null) { maybeEmitEvent(new AfterSaveEvent<>(saved, mappedReplacement, collectionName)); return maybeCallAfterSave(saved, mappedReplacement, collectionName); @@ -1146,7 +1165,7 @@ public T insert(T objectToSave, String collectionName) { } protected void ensureNotIterable(@Nullable Object o) { - if (null != o) { + if (o != null) { if (o.getClass().isArray() || ITERABLE_CLASSES.contains(o.getClass().getName())) { throw new IllegalArgumentException("Cannot use a collection here."); } @@ -2286,7 +2305,7 @@ protected MongoDatabase prepareDatabase(MongoDatabase database) { protected , T> E maybeEmitEvent(E event) { - if (null != eventPublisher) { + if (eventPublisher != null) { eventPublisher.publishEvent(event); } @@ -2295,7 +2314,7 @@ protected , T> E maybeEmitEvent(E event) { protected T maybeCallBeforeConvert(T object, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(BeforeConvertCallback.class, object, collection); } @@ -2304,7 +2323,7 @@ protected T maybeCallBeforeConvert(T object, String collection) { protected T maybeCallBeforeSave(T object, Document document, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(BeforeSaveCallback.class, object, document, collection); } @@ -2313,7 +2332,7 @@ protected T maybeCallBeforeSave(T object, Document document, String collecti protected T maybeCallAfterSave(T object, Document document, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(AfterSaveCallback.class, object, document, collection); } @@ -2322,7 +2341,7 @@ protected T maybeCallAfterSave(T object, Document document, String collectio protected T maybeCallAfterConvert(T object, Document document, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(AfterConvertCallback.class, object, document, collection); } @@ -3110,13 +3129,13 @@ private class ReadDocumentCallback implements DocumentCallback { @Nullable public T doWith(@Nullable Document document) { - if (null != document) { + if (document != null) { maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); } T source = reader.read(type, document); - if (null != source) { + if (source != null) { maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); source = maybeCallAfterConvert(source, document, collectionName); } @@ -3156,14 +3175,14 @@ public T doWith(@Nullable Document document) { Class typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType : targetType; - if (null != document) { + if (document != null) { maybeEmitEvent(new AfterLoadEvent<>(document, targetType, collectionName)); } Object source = reader.read(typeToRead, document); Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; - if (null != result) { + if (result != null) { maybeEmitEvent(new AfterConvertEvent<>(document, result, collectionName)); result = maybeCallAfterConvert(result, document, collectionName); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index b65afdb510..c35f02e5be 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -39,6 +39,7 @@ import org.reactivestreams.Subscriber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -74,7 +75,16 @@ import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; -import org.springframework.data.mongodb.core.convert.*; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.JsonSchemaMapper; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper; +import org.springframework.data.mongodb.core.convert.MongoWriter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.convert.UpdateMapper; import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher; import org.springframework.data.mongodb.core.index.ReactiveIndexOperations; import org.springframework.data.mongodb.core.index.ReactiveMongoPersistentEntityIndexCreator; @@ -109,7 +119,16 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; -import com.mongodb.client.model.*; +import com.mongodb.client.model.CountOptions; +import com.mongodb.client.model.CreateCollectionOptions; +import com.mongodb.client.model.DeleteOptions; +import com.mongodb.client.model.FindOneAndDeleteOptions; +import com.mongodb.client.model.FindOneAndReplaceOptions; +import com.mongodb.client.model.FindOneAndUpdateOptions; +import com.mongodb.client.model.ReplaceOptions; +import com.mongodb.client.model.ReturnDocument; +import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.model.ValidationOptions; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertOneResult; @@ -1145,29 +1164,30 @@ public Mono findAndReplace(Query query, S replacement, FindAndReplaceO Document mappedFields = queryContext.getMappedFields(entity); Document mappedSort = queryContext.getMappedSort(entity); - return Mono.just(PersistableEntityModel.of(replacement, collectionName)) // - .doOnNext(it -> maybeEmitEvent(new BeforeConvertEvent<>(it.getSource(), it.getCollection()))) // - .flatMap(it -> maybeCallBeforeConvert(it.getSource(), it.getCollection()).map(it::mutate)) - .map(it -> it - .addTargetDocument(operations.forEntity(it.getSource()).toMappedDocument(mongoConverter).getDocument())) // - .doOnNext(it -> maybeEmitEvent(new BeforeSaveEvent(it.getSource(), it.getTarget(), it.getCollection()))) // - .flatMap(it -> { + return Mono.defer(() -> { - PersistableEntityModel flowObject = (PersistableEntityModel) it; - return maybeCallBeforeSave(flowObject.getSource(), flowObject.getTarget(), flowObject.getCollection()) - .map(potentiallyModified -> PersistableEntityModel.of(potentiallyModified, flowObject.getTarget(), - flowObject.getCollection())); - }).flatMap(it -> { + PersistableEntityModel pem = PersistableEntityModel.of(replacement, collectionName); - PersistableEntityModel flowObject = (PersistableEntityModel) it; - Mono afterFindAndReplace = doFindAndReplace(flowObject.getCollection(), mappedQuery, - mappedFields, mappedSort, queryContext.getCollation(entityType).orElse(null), - entityType, flowObject.getTarget(), options, resultType); - return afterFindAndReplace.flatMap(saved -> { - maybeEmitEvent(new AfterSaveEvent<>(saved, flowObject.getTarget(), flowObject.getCollection())); - return maybeCallAfterSave(saved, flowObject.getTarget(), flowObject.getCollection()); - }); + maybeEmitEvent(new BeforeConvertEvent<>(pem.getSource(), pem.getCollection())); + + return maybeCallBeforeConvert(pem.getSource(), pem.getCollection()).map(pem::mutate).flatMap(it -> { + PersistableEntityModel mapped = it + .addTargetDocument(operations.forEntity(it.getSource()).toMappedDocument(mongoConverter).getDocument()); + maybeEmitEvent(new BeforeSaveEvent(mapped.getSource(), mapped.getTarget(), mapped.getCollection())); + + return maybeCallBeforeSave(it.getSource(), mapped.getTarget(), mapped.getCollection()) + .map(potentiallyModified -> PersistableEntityModel.of(potentiallyModified, mapped.getTarget(), + mapped.getCollection())); + }).flatMap(it -> { + + Mono afterFindAndReplace = doFindAndReplace(it.getCollection(), mappedQuery, mappedFields, mappedSort, + queryContext.getCollation(entityType).orElse(null), entityType, it.getTarget(), options, resultType); + return afterFindAndReplace.flatMap(saved -> { + maybeEmitEvent(new AfterSaveEvent<>(saved, it.getTarget(), it.getCollection())); + return maybeCallAfterSave(saved, it.getTarget(), it.getCollection()); }); + }); + }); } /* @@ -1314,13 +1334,14 @@ protected Mono doInsert(String collectionName, T objectToSave, MongoWrite AdaptibleEntity entity = operations.forEntity(it.getSource(), mongoConverter.getConversionService()); entity.assertUpdateableIdIfNotSet(); - return PersistableEntityModel.of(entity.initializeVersionProperty(), + PersistableEntityModel model = PersistableEntityModel.of(entity.initializeVersionProperty(), entity.toMappedDocument(writer).getDocument(), it.getCollection()); - }).doOnNext(it -> maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), it.getTarget(), it.getCollection()))) // - .flatMap(it -> { + maybeEmitEvent(new BeforeSaveEvent<>(model.getSource(), model.getTarget(), model.getCollection())); + return model; + })// + .flatMap(it -> { return maybeCallBeforeSave(it.getSource(), it.getTarget(), it.getCollection()).map(it::mutate); - }).flatMap(it -> { return insertDocument(it.getCollection(), it.getTarget(), it.getSource().getClass()).flatMap(id -> { @@ -2588,7 +2609,7 @@ protected Mono doFindAndReplace(String collectionName, Document mappedQue protected , T> E maybeEmitEvent(E event) { - if (null != eventPublisher) { + if (eventPublisher != null) { eventPublisher.publishEvent(event); } @@ -2597,7 +2618,7 @@ protected , T> E maybeEmitEvent(E event) { protected Mono maybeCallBeforeConvert(T object, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(ReactiveBeforeConvertCallback.class, object, collection); } @@ -2606,7 +2627,7 @@ protected Mono maybeCallBeforeConvert(T object, String collection) { protected Mono maybeCallBeforeSave(T object, Document document, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(ReactiveBeforeSaveCallback.class, object, document, collection); } @@ -2615,7 +2636,7 @@ protected Mono maybeCallBeforeSave(T object, Document document, String co protected Mono maybeCallAfterSave(T object, Document document, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(ReactiveAfterSaveCallback.class, object, document, collection); } @@ -2624,7 +2645,7 @@ protected Mono maybeCallAfterSave(T object, Document document, String col protected Mono maybeCallAfterConvert(T object, Document document, String collection) { - if (null != entityCallbacks) { + if (entityCallbacks != null) { return entityCallbacks.callback(ReactiveAfterConvertCallback.class, object, document, collection); } @@ -3092,23 +3113,18 @@ public Mono doWith(Document document) { maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); T source = reader.read(type, document); - if (null != source) { + if (source != null) { maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); + return maybeCallAfterConvert(source, document, collectionName); } - return Mono.defer(() -> { - if (null != source) { - return maybeCallAfterConvert(source, document, collectionName); - } else { - return Mono.empty(); - } - }); + + return Mono.empty(); } } /** - * {@link DocumentCallback} transforming {@link Document} into the given {@code targetType} or - * decorating the {@code sourceType} with a {@literal projection} in case the {@code targetType} is an - * {@literal interface}. + * {@link DocumentCallback} transforming {@link Document} into the given {@code targetType} or decorating the + * {@code sourceType} with a {@literal projection} in case the {@code targetType} is an {@literal interface}. * * @param * @param @@ -3137,17 +3153,12 @@ public Mono doWith(Document document) { Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; T castEntity = (T) result; - if (null != castEntity) { + if (castEntity != null) { maybeEmitEvent(new AfterConvertEvent<>(document, castEntity, collectionName)); + return maybeCallAfterConvert(castEntity, document, collectionName); } - return Mono.defer(() -> { - if (null != castEntity) { - return maybeCallAfterConvert(castEntity, document, collectionName); - } else { - return Mono.empty(); - } - }); + return Mono.empty(); } } @@ -3184,15 +3195,18 @@ static class GeoNearResultDocumentCallback implements DocumentCallback> doWith(Document object) { - final double distance; + double distance = getDistance(object); + + return delegate.doWith(object).map(doWith -> new GeoResult<>(doWith, new Distance(distance, metric))); + } + + double getDistance(Document object) { + if (object.containsKey(distanceField)) { - distance = NumberUtils.convertNumberToTargetClass(object.get(distanceField, Number.class), Double.class); - } else { - distance = Double.NaN; + return NumberUtils.convertNumberToTargetClass(object.get(distanceField, Number.class), Double.class); } - - return delegate.doWith(object) - .map(doWith -> new GeoResult<>(doWith, new Distance(distance, metric))); + + return Double.NaN; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java index 3dc4f04176..7ff740a42d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java @@ -19,22 +19,24 @@ import org.springframework.data.mapping.callback.EntityCallback; /** - * Callback being invoked after a domain object is converted from a Document (when reading from the DB). + * Callback being invoked after a domain object is materialized from a {@link Document} when reading results. * * @author Roman Puchkovskiy + * @author Mark Paluch * @since 3.0 + * @see org.springframework.data.mapping.callback.EntityCallbacks */ @FunctionalInterface public interface AfterConvertCallback extends EntityCallback { /** - * Entity callback method invoked after a domain object is converted from a Document. Can return either the same - * or a modified instance of the domain object. + * Entity callback method invoked after a domain object is materialized from a {@link Document}. Can return either the + * same or a modified instance of the domain object. * * @param entity the domain object (the result of the conversion). * @param document must not be {@literal null}. * @param collection name of the collection. - * @return the domain object that is the result of the conversion from the Document. + * @return the domain object that is the result of reading it from the {@link Document}. */ T onAfterConvert(T entity, Document document, String collection); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java index c22597ca49..bd2152dabf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java @@ -19,7 +19,7 @@ import org.springframework.data.mapping.callback.EntityCallback; /** - * Entity callback triggered after save of a document. + * Entity callback triggered after save of a {@link Document}. * * @author Roman Puchkovskiy * @since 3.0 @@ -28,8 +28,8 @@ public interface AfterSaveCallback extends EntityCallback { /** - * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance - * of the domain object. + * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance of + * the domain object. * * @param entity the domain object that was saved. * @param document {@link Document} representing the {@code entity}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java index c8a43c1939..9b512b0e26 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java @@ -22,6 +22,7 @@ * * @author Mark Paluch * @since 2.2 + * @see org.springframework.data.mapping.callback.EntityCallbacks */ @FunctionalInterface public interface BeforeConvertCallback extends EntityCallback { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java index cdb0e2424f..2c83125085 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java @@ -24,6 +24,7 @@ * @author Mark Paluch * @author Michael J. Simons * @since 2.2 + * @see org.springframework.data.mapping.callback.EntityCallbacks */ @FunctionalInterface public interface BeforeSaveCallback extends EntityCallback { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java index 7a273cf153..5ff16dd3d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java @@ -17,27 +17,28 @@ import org.bson.Document; import org.reactivestreams.Publisher; + import org.springframework.data.mapping.callback.EntityCallback; -import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; /** - * Callback being invoked after a domain object is converted from a Document (when reading from the DB). + * Callback being invoked after a domain object is materialized from a {@link Document} when reading results. * * @author Roman Puchkovskiy + * @author Mark Paluch * @since 3.0 - * @see ReactiveEntityCallbacks + * @see org.springframework.data.mapping.callback.ReactiveEntityCallbacks */ @FunctionalInterface public interface ReactiveAfterConvertCallback extends EntityCallback { /** - * Entity callback method invoked after a domain object is converted from a Document. Can return either the same - * or a modified instance of the domain object. + * Entity callback method invoked after a domain object is materialized from a {@link Document}. Can return either the + * same or a modified instance of the domain object. * * @param entity the domain object (the result of the conversion). * @param document must not be {@literal null}. * @param collection name of the collection. - * @return a {@link Publisher} emitting the domain object that is the result of the conversion from the Document. + * @return a {@link Publisher} emitting the domain object that is the result of reading it from the {@link Document}. */ Publisher onAfterConvert(T entity, Document document, String collection); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java index 64eda738ff..81a209d303 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java @@ -22,7 +22,7 @@ import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; /** - * Entity callback triggered after save of a document. + * Entity callback triggered after save of a {@link Document}. * * @author Roman Puchkovskiy * @since 3.0 @@ -32,8 +32,8 @@ public interface ReactiveAfterSaveCallback extends EntityCallback { /** - * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance - * of the domain object. + * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance of + * the domain object. * * @param entity the domain object that was saved. * @param document {@link Document} representing the {@code entity}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java index a82ca01b93..1590848008 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java @@ -18,14 +18,13 @@ import org.reactivestreams.Publisher; import org.springframework.data.mapping.callback.EntityCallback; -import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; /** * Callback being invoked before a domain object is converted to be persisted. * * @author Mark Paluch * @since 2.2 - * @see ReactiveEntityCallbacks + * @see org.springframework.data.mapping.callback.ReactiveEntityCallbacks */ @FunctionalInterface public interface ReactiveBeforeConvertCallback extends EntityCallback { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java index 3f50ac2916..b8001e2f2a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java @@ -19,14 +19,13 @@ import org.reactivestreams.Publisher; import org.springframework.data.mapping.callback.EntityCallback; -import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; /** * Entity callback triggered before save of a document. * * @author Mark Paluch * @since 2.2 - * @see ReactiveEntityCallbacks + * @see org.springframework.data.mapping.callback.ReactiveEntityCallbacks */ @FunctionalInterface public interface ReactiveBeforeSaveCallback extends EntityCallback { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 5539f53916..44dfead8b6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -19,7 +19,9 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.*; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.math.BigInteger; import java.time.Duration; @@ -39,7 +41,6 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -103,7 +104,6 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; -import com.google.common.collect.ImmutableMap; import com.mongodb.MongoClientSettings; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; @@ -143,7 +143,7 @@ @MockitoSettings(strictness = Strictness.LENIENT) public class MongoTemplateUnitTests extends MongoOperationsUnitTests { - MongoTemplate template; + private MongoTemplate template; @Mock MongoDatabaseFactory factory; @Mock MongoClient mongo; @@ -158,14 +158,14 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Mock UpdateResult updateResult; @Mock DeleteResult deleteResult; - Document commandResultDocument = new Document(); + private Document commandResultDocument = new Document(); - MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); - MappingMongoConverter converter; - MongoMappingContext mappingContext; + private MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; @BeforeEach - public void beforeEach() { + void beforeEach() { when(findIterable.iterator()).thenReturn(cursor); when(factory.getMongoDatabase()).thenReturn(db); @@ -214,23 +214,23 @@ public void beforeEach() { } @Test - public void rejectsNullDatabaseName() { + void rejectsNullDatabaseName() { assertThatIllegalArgumentException().isThrownBy(() -> new MongoTemplate(mongo, null)); } @Test // DATAMONGO-1968 - public void rejectsNullMongo() { + void rejectsNullMongo() { assertThatIllegalArgumentException().isThrownBy(() -> new MongoTemplate((MongoClient) null, "database")); } @Test // DATAMONGO-1968 - public void rejectsNullMongoClient() { + void rejectsNullMongoClient() { assertThatIllegalArgumentException() .isThrownBy(() -> new MongoTemplate((com.mongodb.client.MongoClient) null, "database")); } @Test // DATAMONGO-1870 - public void removeHandlesMongoExceptionProperly() { + void removeHandlesMongoExceptionProperly() { MongoTemplate template = mockOutGetDb(); @@ -238,13 +238,13 @@ public void removeHandlesMongoExceptionProperly() { } @Test - public void defaultsConverterToMappingMongoConverter() { + void defaultsConverterToMappingMongoConverter() { MongoTemplate template = new MongoTemplate(mongo, "database"); assertThat(ReflectionTestUtils.getField(template, "mongoConverter") instanceof MappingMongoConverter).isTrue(); } @Test - public void rejectsNotFoundMapReduceResource() { + void rejectsNotFoundMapReduceResource() { GenericApplicationContext ctx = new GenericApplicationContext(); ctx.refresh(); @@ -255,14 +255,14 @@ public void rejectsNotFoundMapReduceResource() { } @Test // DATAMONGO-322 - public void rejectsEntityWithNullIdIfNotSupportedIdType() { + void rejectsEntityWithNullIdIfNotSupportedIdType() { Object entity = new NotAutogenerateableId(); assertThatExceptionOfType(InvalidDataAccessApiUsageException.class).isThrownBy(() -> template.save(entity)); } @Test // DATAMONGO-322 - public void storesEntityWithSetIdAlthoughNotAutogenerateable() { + void storesEntityWithSetIdAlthoughNotAutogenerateable() { NotAutogenerateableId entity = new NotAutogenerateableId(); entity.id = 1; @@ -271,7 +271,7 @@ public void storesEntityWithSetIdAlthoughNotAutogenerateable() { } @Test // DATAMONGO-322 - public void autogeneratesIdForEntityWithAutogeneratableId() { + void autogeneratesIdForEntityWithAutogeneratableId() { this.converter.afterPropertiesSet(); @@ -285,7 +285,7 @@ public void autogeneratesIdForEntityWithAutogeneratableId() { } @Test // DATAMONGO-1912 - public void autogeneratesIdForMap() { + void autogeneratesIdForMap() { MongoTemplate template = spy(this.template); doReturn(new ObjectId()).when(template).saveDocument(any(String.class), any(Document.class), any(Class.class)); @@ -297,7 +297,7 @@ public void autogeneratesIdForMap() { } @Test // DATAMONGO-374 - public void convertsUpdateConstraintsUsingConverters() { + void convertsUpdateConstraintsUsingConverters() { CustomConversions conversions = new MongoCustomConversions(Collections.singletonList(MyConverter.INSTANCE)); this.converter.setCustomConversions(conversions); @@ -315,7 +315,7 @@ public void convertsUpdateConstraintsUsingConverters() { } @Test // DATAMONGO-474 - public void setsUnpopulatedIdField() { + void setsUnpopulatedIdField() { NotAutogenerateableId entity = new NotAutogenerateableId(); @@ -324,7 +324,7 @@ public void setsUnpopulatedIdField() { } @Test // DATAMONGO-474 - public void doesNotSetAlreadyPopulatedId() { + void doesNotSetAlreadyPopulatedId() { NotAutogenerateableId entity = new NotAutogenerateableId(); entity.id = 5; @@ -334,7 +334,7 @@ public void doesNotSetAlreadyPopulatedId() { } @Test // DATAMONGO-868 - public void findAndModifyShouldBumpVersionByOneWhenVersionFieldNotIncludedInUpdate() { + void findAndModifyShouldBumpVersionByOneWhenVersionFieldNotIncludedInUpdate() { VersionedEntity v = new VersionedEntity(); v.id = 1; @@ -350,7 +350,7 @@ public void findAndModifyShouldBumpVersionByOneWhenVersionFieldNotIncludedInUpda } @Test // DATAMONGO-868 - public void findAndModifyShouldNotBumpVersionByOneWhenVersionFieldAlreadyIncludedInUpdate() { + void findAndModifyShouldNotBumpVersionByOneWhenVersionFieldAlreadyIncludedInUpdate() { VersionedEntity v = new VersionedEntity(); v.id = 1; @@ -368,7 +368,7 @@ public void findAndModifyShouldNotBumpVersionByOneWhenVersionFieldAlreadyInclude } @Test // DATAMONGO-533 - public void registersDefaultEntityIndexCreatorIfApplicationContextHasOneForDifferentMappingContext() { + void registersDefaultEntityIndexCreatorIfApplicationContextHasOneForDifferentMappingContext() { GenericApplicationContext applicationContext = new GenericApplicationContext(); applicationContext.getBeanFactory().registerSingleton("foo", @@ -390,7 +390,7 @@ public boolean matches(MongoPersistentEntityIndexCreator argument) { } @Test // DATAMONGO-566 - public void findAllAndRemoveShouldRetrieveMatchingDocumentsPriorToRemoval() { + void findAllAndRemoveShouldRetrieveMatchingDocumentsPriorToRemoval() { BasicQuery query = new BasicQuery("{'foo':'bar'}"); template.findAllAndRemove(query, VersionedEntity.class); @@ -398,7 +398,7 @@ public void findAllAndRemoveShouldRetrieveMatchingDocumentsPriorToRemoval() { } @Test // DATAMONGO-566 - public void findAllAndRemoveShouldRemoveDocumentsReturedByFindQuery() { + void findAllAndRemoveShouldRemoveDocumentsReturedByFindQuery() { Mockito.when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); Mockito.when(cursor.next()).thenReturn(new org.bson.Document("_id", Integer.valueOf(0))) @@ -415,14 +415,14 @@ public void findAllAndRemoveShouldRemoveDocumentsReturedByFindQuery() { } @Test // DATAMONGO-566 - public void findAllAndRemoveShouldNotTriggerRemoveIfFindResultIsEmpty() { + void findAllAndRemoveShouldNotTriggerRemoveIfFindResultIsEmpty() { template.findAllAndRemove(new BasicQuery("{'foo':'bar'}"), VersionedEntity.class); verify(collection, never()).deleteMany(any(org.bson.Document.class)); } @Test // DATAMONGO-948 - public void sortShouldBeTakenAsIsWhenExecutingQueryWithoutSpecificTypeInformation() { + void sortShouldBeTakenAsIsWhenExecutingQueryWithoutSpecificTypeInformation() { Query query = Query.query(Criteria.where("foo").is("bar")).with(Sort.by("foo")); template.executeQuery(query, "collection1", new DocumentCallbackHandler() { @@ -440,7 +440,7 @@ public void processDocument(Document document) throws MongoException, DataAccess } @Test // DATAMONGO-1166, DATAMONGO-1824 - public void aggregateShouldHonorReadPreferenceWhenSet() { + void aggregateShouldHonorReadPreferenceWhenSet() { template.setReadPreference(ReadPreference.secondary()); @@ -450,7 +450,7 @@ public void aggregateShouldHonorReadPreferenceWhenSet() { } @Test // DATAMONGO-1166, DATAMONGO-1824 - public void aggregateShouldIgnoreReadPreferenceWhenNotSet() { + void aggregateShouldIgnoreReadPreferenceWhenNotSet() { template.aggregate(newAggregation(Aggregation.unwind("foo")), "collection-1", Wrapper.class); @@ -458,7 +458,7 @@ public void aggregateShouldIgnoreReadPreferenceWhenNotSet() { } @Test // DATAMONGO-2153 - public void aggregateShouldHonorOptionsComment() { + void aggregateShouldHonorOptionsComment() { AggregationOptions options = AggregationOptions.builder().comment("expensive").build(); @@ -468,7 +468,7 @@ public void aggregateShouldHonorOptionsComment() { } @Test // DATAMONGO-1166, DATAMONGO-2264 - public void geoNearShouldHonorReadPreferenceWhenSet() { + void geoNearShouldHonorReadPreferenceWhenSet() { template.setReadPreference(ReadPreference.secondary()); @@ -479,7 +479,7 @@ public void geoNearShouldHonorReadPreferenceWhenSet() { } @Test // DATAMONGO-1166, DATAMONGO-2264 - public void geoNearShouldIgnoreReadPreferenceWhenNotSet() { + void geoNearShouldIgnoreReadPreferenceWhenNotSet() { NearQuery query = NearQuery.near(new Point(1, 1)); template.geoNear(query, Wrapper.class); @@ -489,7 +489,7 @@ public void geoNearShouldIgnoreReadPreferenceWhenNotSet() { @Test // DATAMONGO-1334 @Disabled("TODO: mongo3 - a bit hard to tests with the immutable object stuff") - public void mapReduceShouldUseZeroAsDefaultLimit() { + void mapReduceShouldUseZeroAsDefaultLimit() { MongoCursor cursor = mock(MongoCursor.class); MapReduceIterable output = mock(MapReduceIterable.class); @@ -509,7 +509,7 @@ public void mapReduceShouldUseZeroAsDefaultLimit() { } @Test // DATAMONGO-1334 - public void mapReduceShouldPickUpLimitFromQuery() { + void mapReduceShouldPickUpLimitFromQuery() { MongoCursor cursor = mock(MongoCursor.class); MapReduceIterable output = mock(MapReduceIterable.class); @@ -530,7 +530,7 @@ public void mapReduceShouldPickUpLimitFromQuery() { } @Test // DATAMONGO-1334 - public void mapReduceShouldPickUpLimitFromOptions() { + void mapReduceShouldPickUpLimitFromOptions() { MongoCursor cursor = mock(MongoCursor.class); MapReduceIterable output = mock(MapReduceIterable.class); @@ -551,7 +551,7 @@ public void mapReduceShouldPickUpLimitFromOptions() { } @Test // DATAMONGO-1334 - public void mapReduceShouldPickUpLimitFromOptionsWhenQueryIsNotPresent() { + void mapReduceShouldPickUpLimitFromOptionsWhenQueryIsNotPresent() { MongoCursor cursor = mock(MongoCursor.class); MapReduceIterable output = mock(MapReduceIterable.class); @@ -570,7 +570,7 @@ public void mapReduceShouldPickUpLimitFromOptionsWhenQueryIsNotPresent() { } @Test // DATAMONGO-1334 - public void mapReduceShouldPickUpLimitFromOptionsEvenWhenQueryDefinesItDifferently() { + void mapReduceShouldPickUpLimitFromOptionsEvenWhenQueryDefinesItDifferently() { MongoCursor cursor = mock(MongoCursor.class); MapReduceIterable output = mock(MapReduceIterable.class); @@ -592,7 +592,7 @@ public void mapReduceShouldPickUpLimitFromOptionsEvenWhenQueryDefinesItDifferent } @Test // DATAMONGO-1639 - public void beforeConvertEventForUpdateSeesNextVersion() { + void beforeConvertEventForUpdateSeesNextVersion() { when(updateResult.getModifiedCount()).thenReturn(1L); @@ -616,7 +616,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1447 - public void shouldNotAppend$isolatedToNonMulitUpdate() { + void shouldNotAppend$isolatedToNonMulitUpdate() { template.updateFirst(new Query(), new Update().isolated().set("jon", "snow"), Wrapper.class); @@ -630,7 +630,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1447 - public void shouldAppend$isolatedToUpdateMultiEmptyQuery() { + void shouldAppend$isolatedToUpdateMultiEmptyQuery() { template.updateMulti(new Query(), new Update().isolated().set("jon", "snow"), Wrapper.class); @@ -644,7 +644,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1447 - public void shouldAppend$isolatedToUpdateMultiQueryIfNotPresentAndUpdateSetsValue() { + void shouldAppend$isolatedToUpdateMultiQueryIfNotPresentAndUpdateSetsValue() { Update update = new Update().isolated().set("jon", "snow"); Query query = new BasicQuery("{'eddard':'stark'}"); @@ -661,7 +661,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1447 - public void shouldNotAppend$isolatedToUpdateMultiQueryIfNotPresentAndUpdateDoesNotSetValue() { + void shouldNotAppend$isolatedToUpdateMultiQueryIfNotPresentAndUpdateDoesNotSetValue() { Update update = new Update().set("jon", "snow"); Query query = new BasicQuery("{'eddard':'stark'}"); @@ -678,7 +678,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1447 - public void shouldNotOverwrite$isolatedToUpdateMultiQueryIfPresentAndUpdateDoesNotSetValue() { + void shouldNotOverwrite$isolatedToUpdateMultiQueryIfPresentAndUpdateDoesNotSetValue() { Update update = new Update().set("jon", "snow"); Query query = new BasicQuery("{'eddard':'stark', '$isolated' : 1}"); @@ -695,7 +695,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1447 - public void shouldNotOverwrite$isolatedToUpdateMultiQueryIfPresentAndUpdateSetsValue() { + void shouldNotOverwrite$isolatedToUpdateMultiQueryIfPresentAndUpdateSetsValue() { Update update = new Update().isolated().set("jon", "snow"); Query query = new BasicQuery("{'eddard':'stark', '$isolated' : 0}"); @@ -712,7 +712,7 @@ public void onBeforeConvert(BeforeConvertEvent event) { } @Test // DATAMONGO-1311 - public void executeQueryShouldUseBatchSizeWhenPresent() { + void executeQueryShouldUseBatchSizeWhenPresent() { when(findIterable.batchSize(anyInt())).thenReturn(findIterable); @@ -723,7 +723,7 @@ public void executeQueryShouldUseBatchSizeWhenPresent() { } @Test // DATAMONGO-1518 - public void executeQueryShouldUseCollationWhenPresent() { + void executeQueryShouldUseCollationWhenPresent() { template.executeQuery(new BasicQuery("{}").collation(Collation.of("fr")), "collection-1", val -> {}); @@ -731,7 +731,7 @@ public void executeQueryShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void streamQueryShouldUseCollationWhenPresent() { + void streamQueryShouldUseCollationWhenPresent() { template.stream(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).next(); @@ -739,7 +739,7 @@ public void streamQueryShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findShouldUseCollationWhenPresent() { + void findShouldUseCollationWhenPresent() { template.find(new BasicQuery("{'foo' : 'bar'}").collation(Collation.of("fr")), AutogenerateableId.class); @@ -747,7 +747,7 @@ public void findShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findOneShouldUseCollationWhenPresent() { + void findOneShouldUseCollationWhenPresent() { template.findOne(new BasicQuery("{'foo' : 'bar'}").collation(Collation.of("fr")), AutogenerateableId.class); @@ -755,7 +755,7 @@ public void findOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void existsShouldUseCollationWhenPresent() { + void existsShouldUseCollationWhenPresent() { template.exists(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class); @@ -767,7 +767,7 @@ public void existsShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findAndModfiyShoudUseCollationWhenPresent() { + void findAndModfiyShoudUseCollationWhenPresent() { template.findAndModify(new BasicQuery("{}").collation(Collation.of("fr")), new Update(), AutogenerateableId.class); @@ -778,7 +778,7 @@ public void findAndModfiyShoudUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findAndRemoveShouldUseCollationWhenPresent() { + void findAndRemoveShouldUseCollationWhenPresent() { template.findAndRemove(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class); @@ -789,7 +789,7 @@ public void findAndRemoveShouldUseCollationWhenPresent() { } @Test // DATAMONGO-2196 - public void removeShouldApplyWriteConcern() { + void removeShouldApplyWriteConcern() { Person person = new Person(); person.id = "id-1"; @@ -802,7 +802,7 @@ public void removeShouldApplyWriteConcern() { } @Test // DATAMONGO-1518 - public void findAndRemoveManyShouldUseCollationWhenPresent() { + void findAndRemoveManyShouldUseCollationWhenPresent() { template.doRemove("collection-1", new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class, true); @@ -814,7 +814,7 @@ public void findAndRemoveManyShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void updateOneShouldUseCollationWhenPresent() { + void updateOneShouldUseCollationWhenPresent() { template.updateFirst(new BasicQuery("{}").collation(Collation.of("fr")), new Update().set("foo", "bar"), AutogenerateableId.class); @@ -826,7 +826,7 @@ public void updateOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void updateManyShouldUseCollationWhenPresent() { + void updateManyShouldUseCollationWhenPresent() { template.updateMulti(new BasicQuery("{}").collation(Collation.of("fr")), new Update().set("foo", "bar"), AutogenerateableId.class); @@ -838,7 +838,7 @@ public void updateManyShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void replaceOneShouldUseCollationWhenPresent() { + void replaceOneShouldUseCollationWhenPresent() { template.updateFirst(new BasicQuery("{}").collation(Collation.of("fr")), new Update(), AutogenerateableId.class); @@ -849,7 +849,7 @@ public void replaceOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518, DATAMONGO-1824 - public void aggregateShouldUseCollationWhenPresent() { + void aggregateShouldUseCollationWhenPresent() { Aggregation aggregation = newAggregation(project("id")) .withOptions(newAggregationOptions().collation(Collation.of("fr")).build()); @@ -859,7 +859,7 @@ public void aggregateShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1824 - public void aggregateShouldUseBatchSizeWhenPresent() { + void aggregateShouldUseBatchSizeWhenPresent() { Aggregation aggregation = newAggregation(project("id")) .withOptions(newAggregationOptions().collation(Collation.of("fr")).cursorBatchSize(100).build()); @@ -869,7 +869,7 @@ public void aggregateShouldUseBatchSizeWhenPresent() { } @Test // DATAMONGO-1518 - public void mapReduceShouldUseCollationWhenPresent() { + void mapReduceShouldUseCollationWhenPresent() { template.mapReduce("", "", "", MapReduceOptions.options().collation(Collation.of("fr")), AutogenerateableId.class); @@ -877,7 +877,7 @@ public void mapReduceShouldUseCollationWhenPresent() { } @Test // DATAMONGO-2027 - public void mapReduceShouldUseOutputCollectionWhenPresent() { + void mapReduceShouldUseOutputCollectionWhenPresent() { template.mapReduce("", "", "", MapReduceOptions.options().outputCollection("out-collection"), AutogenerateableId.class); @@ -886,7 +886,7 @@ public void mapReduceShouldUseOutputCollectionWhenPresent() { } @Test // DATAMONGO-2027 - public void mapReduceShouldNotUseOutputCollectionForInline() { + void mapReduceShouldNotUseOutputCollectionForInline() { template.mapReduce("", "", "", MapReduceOptions.options().outputCollection("out-collection").outputTypeInline(), AutogenerateableId.class); @@ -895,7 +895,7 @@ public void mapReduceShouldNotUseOutputCollectionForInline() { } @Test // DATAMONGO-2027 - public void mapReduceShouldUseOutputActionWhenPresent() { + void mapReduceShouldUseOutputActionWhenPresent() { template.mapReduce("", "", "", MapReduceOptions.options().outputCollection("out-collection").outputTypeMerge(), AutogenerateableId.class); @@ -904,7 +904,7 @@ public void mapReduceShouldUseOutputActionWhenPresent() { } @Test // DATAMONGO-2027 - public void mapReduceShouldUseOutputDatabaseWhenPresent() { + void mapReduceShouldUseOutputDatabaseWhenPresent() { template.mapReduce("", "", "", MapReduceOptions.options().outputDatabase("out-database").outputCollection("out-collection").outputTypeMerge(), @@ -914,7 +914,7 @@ public void mapReduceShouldUseOutputDatabaseWhenPresent() { } @Test // DATAMONGO-2027 - public void mapReduceShouldNotUseOutputDatabaseForInline() { + void mapReduceShouldNotUseOutputDatabaseForInline() { template.mapReduce("", "", "", MapReduceOptions.options().outputDatabase("out-database").outputTypeInline(), AutogenerateableId.class); @@ -923,7 +923,7 @@ public void mapReduceShouldNotUseOutputDatabaseForInline() { } @Test // DATAMONGO-1518, DATAMONGO-2264 - public void geoNearShouldUseCollationWhenPresent() { + void geoNearShouldUseCollationWhenPresent() { NearQuery query = NearQuery.near(0D, 0D).query(new BasicQuery("{}").collation(Collation.of("fr"))); template.geoNear(query, AutogenerateableId.class); @@ -932,7 +932,7 @@ public void geoNearShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void groupShouldUseCollationWhenPresent() { + void groupShouldUseCollationWhenPresent() { commandResultDocument.append("retval", Collections.emptySet()); template.group("collection-1", GroupBy.key("id").reduceFunction("bar").collation(Collation.of("fr")), @@ -946,7 +946,7 @@ public void groupShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1880 - public void countShouldUseCollationWhenPresent() { + void countShouldUseCollationWhenPresent() { template.count(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class); @@ -958,7 +958,7 @@ public void countShouldUseCollationWhenPresent() { } @Test // DATAMONGO-2360 - public void countShouldApplyQueryHintIfPresent() { + void countShouldApplyQueryHintIfPresent() { Document queryHint = new Document("age", 1); template.count(new BasicQuery("{}").withHint(queryHint), AutogenerateableId.class); @@ -970,7 +970,7 @@ public void countShouldApplyQueryHintIfPresent() { } @Test // DATAMONGO-2365 - public void countShouldApplyQueryHintAsIndexNameIfPresent() { + void countShouldApplyQueryHintAsIndexNameIfPresent() { template.count(new BasicQuery("{}").withHint("idx-1"), AutogenerateableId.class); @@ -981,7 +981,7 @@ public void countShouldApplyQueryHintAsIndexNameIfPresent() { } @Test // DATAMONGO-1733 - public void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() { + void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonProjection.class, CursorPreparer.NO_OP_PREPARER); @@ -990,7 +990,7 @@ public void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFie } @Test // DATAMONGO-1733 - public void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFields() { + void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFields() { template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, PersonProjection.class, CursorPreparer.NO_OP_PREPARER); @@ -999,7 +999,7 @@ public void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFiel } @Test // DATAMONGO-1733 - public void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { + void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonSpELProjection.class, CursorPreparer.NO_OP_PREPARER); @@ -1008,7 +1008,7 @@ public void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { } @Test // DATAMONGO-1733, DATAMONGO-2041 - public void appliesFieldsToDtoProjection() { + void appliesFieldsToDtoProjection() { template.doFind("star-wars", new Document(), new Document(), Person.class, Jedi.class, CursorPreparer.NO_OP_PREPARER); @@ -1017,7 +1017,7 @@ public void appliesFieldsToDtoProjection() { } @Test // DATAMONGO-1733 - public void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { + void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, Jedi.class, CursorPreparer.NO_OP_PREPARER); @@ -1026,7 +1026,7 @@ public void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { } @Test // DATAMONGO-1733 - public void doesNotApplyFieldsWhenTargetIsNotAProjection() { + void doesNotApplyFieldsWhenTargetIsNotAProjection() { template.doFind("star-wars", new Document(), new Document(), Person.class, Person.class, CursorPreparer.NO_OP_PREPARER); @@ -1035,7 +1035,7 @@ public void doesNotApplyFieldsWhenTargetIsNotAProjection() { } @Test // DATAMONGO-1733 - public void doesNotApplyFieldsWhenTargetExtendsDomainType() { + void doesNotApplyFieldsWhenTargetExtendsDomainType() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonExtended.class, CursorPreparer.NO_OP_PREPARER); @@ -1044,7 +1044,7 @@ public void doesNotApplyFieldsWhenTargetExtendsDomainType() { } @Test // DATAMONGO-1348, DATAMONGO-2264 - public void geoNearShouldMapQueryCorrectly() { + void geoNearShouldMapQueryCorrectly() { NearQuery query = NearQuery.near(new Point(1, 1)); query.query(Query.query(Criteria.where("customName").is("rand al'thor"))); @@ -1061,7 +1061,7 @@ public void geoNearShouldMapQueryCorrectly() { } @Test // DATAMONGO-1348, DATAMONGO-2264 - public void geoNearShouldMapGeoJsonPointCorrectly() { + void geoNearShouldMapGeoJsonPointCorrectly() { NearQuery query = NearQuery.near(new GeoJsonPoint(1, 2)); query.query(Query.query(Criteria.where("customName").is("rand al'thor"))); @@ -1078,7 +1078,7 @@ public void geoNearShouldMapGeoJsonPointCorrectly() { } @Test // DATAMONGO-2155 - public void saveVersionedEntityShouldCallUpdateCorrectly() { + void saveVersionedEntityShouldCallUpdateCorrectly() { when(updateResult.getModifiedCount()).thenReturn(1L); @@ -1099,7 +1099,7 @@ public void saveVersionedEntityShouldCallUpdateCorrectly() { } @Test // DATAMONGO-1783 - public void usesQueryOffsetForCountOperation() { + void usesQueryOffsetForCountOperation() { template.count(new BasicQuery("{}").skip(100), AutogenerateableId.class); @@ -1110,7 +1110,7 @@ public void usesQueryOffsetForCountOperation() { } @Test // DATAMONGO-1783 - public void usesQueryLimitForCountOperation() { + void usesQueryLimitForCountOperation() { template.count(new BasicQuery("{}").limit(10), AutogenerateableId.class); @@ -1121,7 +1121,7 @@ public void usesQueryLimitForCountOperation() { } @Test // DATAMONGO-2215 - public void updateShouldApplyArrayFilters() { + void updateShouldApplyArrayFilters() { template.updateFirst(new BasicQuery("{}"), new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)), @@ -1135,7 +1135,7 @@ public void updateShouldApplyArrayFilters() { } @Test // DATAMONGO-2215 - public void findAndModifyShouldApplyArrayFilters() { + void findAndModifyShouldApplyArrayFilters() { template.findAndModify(new BasicQuery("{}"), new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)), @@ -1149,7 +1149,7 @@ public void findAndModifyShouldApplyArrayFilters() { } @Test // DATAMONGO-1854 - public void streamQueryShouldUseDefaultCollationWhenPresent() { + void streamQueryShouldUseDefaultCollationWhenPresent() { template.stream(new BasicQuery("{}"), Sith.class).next(); @@ -1157,7 +1157,7 @@ public void streamQueryShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findShouldNotUseCollationWhenNoDefaultPresent() { + void findShouldNotUseCollationWhenNoDefaultPresent() { template.find(new BasicQuery("{'foo' : 'bar'}"), Jedi.class); @@ -1165,7 +1165,7 @@ public void findShouldNotUseCollationWhenNoDefaultPresent() { } @Test // DATAMONGO-1854 - public void findShouldUseDefaultCollationWhenPresent() { + void findShouldUseDefaultCollationWhenPresent() { template.find(new BasicQuery("{'foo' : 'bar'}"), Sith.class); @@ -1173,7 +1173,7 @@ public void findShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findOneShouldUseDefaultCollationWhenPresent() { + void findOneShouldUseDefaultCollationWhenPresent() { template.findOne(new BasicQuery("{'foo' : 'bar'}"), Sith.class); @@ -1181,7 +1181,7 @@ public void findOneShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void existsShouldUseDefaultCollationWhenPresent() { + void existsShouldUseDefaultCollationWhenPresent() { template.exists(new BasicQuery("{}"), Sith.class); @@ -1193,7 +1193,7 @@ public void existsShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndModfiyShoudUseDefaultCollationWhenPresent() { + void findAndModfiyShoudUseDefaultCollationWhenPresent() { template.findAndModify(new BasicQuery("{}"), new Update(), Sith.class); @@ -1205,7 +1205,7 @@ public void findAndModfiyShoudUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndRemoveShouldUseDefaultCollationWhenPresent() { + void findAndRemoveShouldUseDefaultCollationWhenPresent() { template.findAndRemove(new BasicQuery("{}"), Sith.class); @@ -1217,7 +1217,7 @@ public void findAndRemoveShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void createCollectionShouldNotCollationIfNotPresent() { + void createCollectionShouldNotCollationIfNotPresent() { template.createCollection(AutogenerateableId.class); @@ -1228,7 +1228,7 @@ public void createCollectionShouldNotCollationIfNotPresent() { } @Test // DATAMONGO-1854 - public void createCollectionShouldApplyDefaultCollation() { + void createCollectionShouldApplyDefaultCollation() { template.createCollection(Sith.class); @@ -1240,7 +1240,7 @@ public void createCollectionShouldApplyDefaultCollation() { } @Test // DATAMONGO-1854 - public void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { + void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { template.createCollection(Sith.class, CollectionOptions.just(Collation.of("en_US"))); @@ -1252,7 +1252,7 @@ public void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull() { + void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull() { template.createCollection(Sith.class, null); @@ -1264,7 +1264,7 @@ public void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull( } @Test // DATAMONGO-1854 - public void aggreateShouldUseDefaultCollationIfPresent() { + void aggreateShouldUseDefaultCollationIfPresent() { template.aggregate(newAggregation(Sith.class, project("id")), AutogenerateableId.class, Document.class); @@ -1272,7 +1272,7 @@ public void aggreateShouldUseDefaultCollationIfPresent() { } @Test // DATAMONGO-1854 - public void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { + void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { template.aggregateStream(newAggregation(Sith.class, project("id")).withOptions( newAggregationOptions().collation(Collation.of("fr")).build()), AutogenerateableId.class, Document.class); @@ -1281,7 +1281,7 @@ public void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent } @Test // DATAMONGO-1854 - public void aggreateStreamShouldUseDefaultCollationIfPresent() { + void aggreateStreamShouldUseDefaultCollationIfPresent() { template.aggregate(newAggregation(Sith.class, project("id")), AutogenerateableId.class, Document.class); @@ -1289,7 +1289,7 @@ public void aggreateStreamShouldUseDefaultCollationIfPresent() { } @Test // DATAMONGO-1854 - public void aggreateStreamShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { + void aggreateStreamShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { template.aggregateStream(newAggregation(Sith.class, project("id")).withOptions( newAggregationOptions().collation(Collation.of("fr")).build()), AutogenerateableId.class, Document.class); @@ -1298,7 +1298,7 @@ public void aggreateStreamShouldUseCollationFromOptionsEvenIfDefaultCollationIsP } @Test // DATAMONGO-2390 - public void aggregateShouldNoApplyZeroOrNegativeMaxTime() { + void aggregateShouldNoApplyZeroOrNegativeMaxTime() { template.aggregate( newAggregation(Sith.class, project("id")).withOptions(newAggregationOptions().maxTime(Duration.ZERO).build()), @@ -1310,7 +1310,7 @@ public void aggregateShouldNoApplyZeroOrNegativeMaxTime() { } @Test // DATAMONGO-2390 - public void aggregateShouldApplyMaxTimeIfSet() { + void aggregateShouldApplyMaxTimeIfSet() { template.aggregate(newAggregation(Sith.class, project("id")).withOptions( newAggregationOptions().maxTime(Duration.ofSeconds(10)).build()), AutogenerateableId.class, Document.class); @@ -1319,7 +1319,7 @@ public void aggregateShouldApplyMaxTimeIfSet() { } @Test // DATAMONGO-1854 - public void findAndReplaceShouldUseCollationWhenPresent() { + void findAndReplaceShouldUseCollationWhenPresent() { template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new AutogenerateableId()); @@ -1330,7 +1330,7 @@ public void findAndReplaceShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findOneWithSortShouldUseCollationWhenPresent() { + void findOneWithSortShouldUseCollationWhenPresent() { template.findOne(new BasicQuery("{}").collation(Collation.of("fr")).with(Sort.by("id")), Sith.class); @@ -1338,7 +1338,7 @@ public void findOneWithSortShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findOneWithSortShouldUseDefaultCollationWhenPresent() { + void findOneWithSortShouldUseDefaultCollationWhenPresent() { template.findOne(new BasicQuery("{}").with(Sort.by("id")), Sith.class); @@ -1346,7 +1346,7 @@ public void findOneWithSortShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndReplaceShouldUseDefaultCollationWhenPresent() { + void findAndReplaceShouldUseDefaultCollationWhenPresent() { template.findAndReplace(new BasicQuery("{}"), new Sith()); @@ -1357,7 +1357,7 @@ public void findAndReplaceShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { + void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new Sith()); @@ -1368,7 +1368,7 @@ public void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { } @Test // DATAMONGO-1854 - public void findDistinctShouldUseDefaultCollationWhenPresent() { + void findDistinctShouldUseDefaultCollationWhenPresent() { template.findDistinct(new BasicQuery("{}"), "name", Sith.class, String.class); @@ -1376,7 +1376,7 @@ public void findDistinctShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findDistinctPreferCollationFromQueryOverDefaultCollation() { + void findDistinctPreferCollationFromQueryOverDefaultCollation() { template.findDistinct(new BasicQuery("{}").collation(Collation.of("fr")), "name", Sith.class, String.class); @@ -1384,7 +1384,7 @@ public void findDistinctPreferCollationFromQueryOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void updateFirstShouldUseDefaultCollationWhenPresent() { + void updateFirstShouldUseDefaultCollationWhenPresent() { template.updateFirst(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class); @@ -1396,7 +1396,7 @@ public void updateFirstShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { + void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { template.updateFirst(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class); @@ -1408,7 +1408,7 @@ public void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void updateMultiShouldUseDefaultCollationWhenPresent() { + void updateMultiShouldUseDefaultCollationWhenPresent() { template.updateMulti(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class); @@ -1420,7 +1420,7 @@ public void updateMultiShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { + void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { template.updateMulti(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class); @@ -1432,7 +1432,7 @@ public void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void removeShouldUseDefaultCollationWhenPresent() { + void removeShouldUseDefaultCollationWhenPresent() { template.remove(new BasicQuery("{}"), Sith.class); @@ -1444,7 +1444,7 @@ public void removeShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void removeShouldPreferExplicitCollationOverDefaultCollation() { + void removeShouldPreferExplicitCollationOverDefaultCollation() { template.remove(new BasicQuery("{}").collation(Collation.of("fr")), Sith.class); @@ -1456,7 +1456,7 @@ public void removeShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void mapReduceShouldUseDefaultCollationWhenPresent() { + void mapReduceShouldUseDefaultCollationWhenPresent() { template.mapReduce("", "", "", MapReduceOptions.options(), Sith.class); @@ -1464,7 +1464,7 @@ public void mapReduceShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void mapReduceShouldPreferExplicitCollationOverDefaultCollation() { + void mapReduceShouldPreferExplicitCollationOverDefaultCollation() { template.mapReduce("", "", "", MapReduceOptions.options().collation(Collation.of("fr")), Sith.class); @@ -1472,7 +1472,7 @@ public void mapReduceShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-2261 - public void saveShouldInvokeCallbacks() { + void saveShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -1490,7 +1490,7 @@ public void saveShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void insertShouldInvokeCallbacks() { + void insertShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -1508,7 +1508,7 @@ public void insertShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void insertAllShouldInvokeCallbacks() { + void insertAllShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -1530,7 +1530,7 @@ public void insertAllShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void findAndReplaceShouldInvokeCallbacks() { + void findAndReplaceShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -1548,7 +1548,7 @@ public void findAndReplaceShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void publishesEventsAndEntityCallbacksInOrder() { + void publishesEventsAndEntityCallbacksInOrder() { BeforeConvertCallback beforeConvertCallback = new BeforeConvertCallback() { @@ -1607,7 +1607,7 @@ public void onBeforeSave(BeforeSaveEvent event) { } @Test // DATAMONGO-2261 - public void beforeSaveCallbackAllowsTargetDocumentModifications() { + void beforeSaveCallbackAllowsTargetDocumentModifications() { BeforeSaveCallback beforeSaveCallback = new BeforeSaveCallback() { @@ -1638,7 +1638,7 @@ public Person onBeforeSave(Person entity, Document document, String collection) } @Test // DATAMONGO-2307 - public void beforeSaveCallbackAllowsTargetEntityModificationsUsingSave() { + void beforeSaveCallbackAllowsTargetEntityModificationsUsingSave() { StaticApplicationContext ctx = new StaticApplicationContext(); ctx.registerBean(BeforeSaveCallback.class, this::beforeSaveCallbackReturningNewPersonWithTransientAttribute); @@ -1656,7 +1656,7 @@ public void beforeSaveCallbackAllowsTargetEntityModificationsUsingSave() { } @Test // DATAMONGO-2307 - public void beforeSaveCallbackAllowsTargetEntityModificationsUsingInsert() { + void beforeSaveCallbackAllowsTargetEntityModificationsUsingInsert() { StaticApplicationContext ctx = new StaticApplicationContext(); ctx.registerBean(BeforeSaveCallback.class, this::beforeSaveCallbackReturningNewPersonWithTransientAttribute); @@ -1676,12 +1676,12 @@ public void beforeSaveCallbackAllowsTargetEntityModificationsUsingInsert() { // TODO: additional tests for what is when saved. @Test // DATAMONGO-2261 - public void entityCallbacksAreNotSetByDefault() { + void entityCallbacksAreNotSetByDefault() { Assertions.assertThat(ReflectionTestUtils.getField(template, "entityCallbacks")).isNull(); } @Test // DATAMONGO-2261 - public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { + void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { ApplicationContext ctx = new StaticApplicationContext(); template.setApplicationContext(ctx); @@ -1690,7 +1690,7 @@ public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { } @Test // DATAMONGO-2261 - public void setterForEntityCallbackOverridesContextInitializedOnes() { + void setterForEntityCallbackOverridesContextInitializedOnes() { ApplicationContext ctx = new StaticApplicationContext(); template.setApplicationContext(ctx); @@ -1702,7 +1702,7 @@ public void setterForEntityCallbackOverridesContextInitializedOnes() { } @Test // DATAMONGO-2261 - public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { + void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { EntityCallbacks callbacks = EntityCallbacks.create(); ApplicationContext ctx = new StaticApplicationContext(); @@ -1714,7 +1714,7 @@ public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallback } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { template.find(new Query().slaveOk(), AutogenerateableId.class); @@ -1722,7 +1722,7 @@ public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { template.findOne(new Query().slaveOk(), AutogenerateableId.class); @@ -1730,7 +1730,7 @@ public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOn } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { template.findDistinct(new Query().slaveOk(), "name", AutogenerateableId.class, String.class); @@ -1738,14 +1738,14 @@ public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDi } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForStream() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForStream() { template.stream(new Query().slaveOk(), AutogenerateableId.class); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } @Test // DATAMONGO-2331 - public void updateShouldAllowAggregationExpressions() { + void updateShouldAllowAggregationExpressions() { AggregationUpdate update = AggregationUpdate.update().set("total") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); @@ -1761,7 +1761,7 @@ public void updateShouldAllowAggregationExpressions() { } @Test // DATAMONGO-2331 - public void updateShouldAllowMultipleAggregationExpressions() { + void updateShouldAllowMultipleAggregationExpressions() { AggregationUpdate update = AggregationUpdate.update() // .set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) // @@ -1789,7 +1789,7 @@ public void updateShouldAllowMultipleAggregationExpressions() { } @Test // DATAMONGO-2331 - public void updateShouldMapAggregationExpressionToDomainType() { + void updateShouldMapAggregationExpressionToDomainType() { AggregationUpdate update = AggregationUpdate.update().set("name") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); @@ -1805,7 +1805,7 @@ public void updateShouldMapAggregationExpressionToDomainType() { } @Test // DATAMONGO-2331 - public void updateShouldPassOnUnsetCorrectly() { + void updateShouldPassOnUnsetCorrectly() { SetOperation setOperation = SetOperation.builder().set("status").toValue("Modified").and().set("comments") .toValue(Fields.fields("misc1").and("misc2").asList()); @@ -1825,7 +1825,7 @@ public void updateShouldPassOnUnsetCorrectly() { } @Test // DATAMONGO-2331 - public void updateShouldMapAggregationUnsetToDomainType() { + void updateShouldMapAggregationUnsetToDomainType() { AggregationUpdate update = AggregationUpdate.update(); update.unset("name"); @@ -1932,150 +1932,136 @@ void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { } @Test // DATAMONGO-2479 - public void findShouldInvokeAfterConvertCallback() { + void findShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(findIterable.iterator()).thenReturn(new OneElementCursor<>(document)); template.find(new Query(), Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); - } - - private Document initialLukeDocument() { - return new Document(ImmutableMap.of( - "_id", "init", - "firstname", "luke" - )); - } - - private Person initialLuke() { - Person expectedEnitty = new Person(); - expectedEnitty.id = "init"; - expectedEnitty.firstname = "luke"; - return expectedEnitty; + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findByIdShouldInvokeAfterConvertCallback() { + void findByIdShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(findIterable.first()).thenReturn(document); template.findById("init", Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findOneShouldInvokeAfterConvertCallback() { + void findOneShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(findIterable.first()).thenReturn(document); template.findOne(new Query(), Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findAllShouldInvokeAfterConvertCallback() { + void findAllShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(findIterable.iterator()).thenReturn(new OneElementCursor<>(document)); template.findAll(Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findAndModifyShouldInvokeAfterConvertCallback() { + void findAndModifyShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(document); template.findAndModify(new Query(), new Update(), Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findAndRemoveShouldInvokeAfterConvertCallback() { + void findAndRemoveShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(document); template.findAndRemove(new Query(), Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findAllAndRemoveShouldInvokeAfterConvertCallback() { + void findAllAndRemoveShouldInvokeAfterConvertCallback() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(findIterable.iterator()).thenReturn(new OneElementCursor<>(document)); template.findAllAndRemove(new Query(), Person.class); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); } @Test // DATAMONGO-2479 - public void findAndReplaceShouldInvokeAfterConvertCallbacks() { + void findAndReplaceShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(document); Person saved = template.findAndReplace(new Query(), entity); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(saved.id).isEqualTo("after-convert"); } @Test // DATAMONGO-2479 - public void saveShouldInvokeAfterSaveCallbacks() { + void saveShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); Person saved = template.save(entity); @@ -2084,13 +2070,13 @@ public void saveShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void insertShouldInvokeAfterSaveCallbacks() { + void insertShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); Person saved = template.insert(entity); @@ -2099,7 +2085,7 @@ public void insertShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void insertAllShouldInvokeAfterSaveCallbacks() { + void insertAllShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); @@ -2120,25 +2106,25 @@ public void insertAllShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void findAndReplaceShouldInvokeAfterSaveCallbacks() { + void findAndReplaceShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(document); Person saved = template.findAndReplace(new Query(), entity); - verify(afterSaveCallback).onAfterSave(eq(initialLuke()), any(), anyString()); + verify(afterSaveCallback).onAfterSave(eq(new Person("init", "luke")), any(), anyString()); assertThat(saved.id).isEqualTo("after-save"); } @Test // DATAMONGO-2479 - public void findAndReplaceShouldEmitAfterSaveEvent() { + void findAndReplaceShouldEmitAfterSaveEvent() { AbstractMongoEventListener eventListener = new AbstractMongoEventListener() { @@ -2156,9 +2142,9 @@ public void onAfterSave(AfterSaveEvent event) { template.setApplicationContext(ctx); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(document); Person saved = template.findAndReplace(new Query(), entity); @@ -2197,6 +2183,8 @@ public String convert(AutogenerateableId source) { @Data @org.springframework.data.mongodb.core.mapping.Document(collection = "star-wars") + @AllArgsConstructor + @NoArgsConstructor static class Person { @Id String id; @@ -2350,10 +2338,12 @@ static class ValueCapturingAfterSaveCallback extends ValueCapturingEntityCallbac public Person onAfterSave(Person entity, Document document, String collection) { capture(entity); - return new Person() {{ - id = "after-save"; - firstname = entity.firstname; - }}; + return new Person() { + { + id = "after-save"; + firstname = entity.firstname; + } + }; } } @@ -2364,10 +2354,12 @@ static class ValueCapturingAfterConvertCallback extends ValueCapturingEntityCall public Person onAfterConvert(Person entity, Document document, String collection) { capture(entity); - return new Person() {{ - id = "after-convert"; - firstname = entity.firstname; - }}; + return new Person() { + { + id = "after-convert"; + firstname = entity.firstname; + } + }; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index f95c5fe67d..506a4e9e21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -20,7 +20,9 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.assertThat; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -86,7 +88,6 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; -import com.google.common.collect.ImmutableMap; import com.mongodb.MongoClientSettings; import com.mongodb.ReadPreference; import com.mongodb.client.model.CountOptions; @@ -120,7 +121,7 @@ @MockitoSettings(strictness = Strictness.LENIENT) public class ReactiveMongoTemplateUnitTests { - ReactiveMongoTemplate template; + private ReactiveMongoTemplate template; @Mock SimpleReactiveMongoDatabaseFactory factory; @Mock MongoClient mongoClient; @@ -136,12 +137,12 @@ public class ReactiveMongoTemplateUnitTests { @Mock Publisher deletePublisher; @Mock MapReducePublisher mapReducePublisher; - MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); - MappingMongoConverter converter; - MongoMappingContext mappingContext; + private MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; @BeforeEach - public void beforeEach() { + void beforeEach() { when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); @@ -187,23 +188,23 @@ public void beforeEach() { } @Test // DATAMONGO-1444 - public void rejectsNullDatabaseName() { + void rejectsNullDatabaseName() { assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMongoTemplate(mongoClient, null)); } @Test // DATAMONGO-1444 - public void rejectsNullMongo() { + void rejectsNullMongo() { assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMongoTemplate(null, "database")); } @Test // DATAMONGO-1444 - public void defaultsConverterToMappingMongoConverter() throws Exception { + void defaultsConverterToMappingMongoConverter() throws Exception { ReactiveMongoTemplate template = new ReactiveMongoTemplate(mongoClient, "database"); assertThat(ReflectionTestUtils.getField(template, "mongoConverter") instanceof MappingMongoConverter).isTrue(); } @Test // DATAMONGO-1912 - public void autogeneratesIdForMap() { + void autogeneratesIdForMap() { ReactiveMongoTemplate template = spy(this.template); doReturn(Mono.just(new ObjectId())).when(template).saveDocument(any(String.class), any(Document.class), @@ -217,7 +218,7 @@ public void autogeneratesIdForMap() { } @Test // DATAMONGO-1311 - public void executeQueryShouldUseBatchSizeWhenPresent() { + void executeQueryShouldUseBatchSizeWhenPresent() { when(findPublisher.batchSize(anyInt())).thenReturn(findPublisher); @@ -228,7 +229,7 @@ public void executeQueryShouldUseBatchSizeWhenPresent() { } @Test // DATAMONGO-1518 - public void findShouldUseCollationWhenPresent() { + void findShouldUseCollationWhenPresent() { template.find(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe(); @@ -237,7 +238,7 @@ public void findShouldUseCollationWhenPresent() { // @Test // DATAMONGO-1518 - public void findOneShouldUseCollationWhenPresent() { + void findOneShouldUseCollationWhenPresent() { template.findOne(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe(); @@ -245,7 +246,7 @@ public void findOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void existsShouldUseCollationWhenPresent() { + void existsShouldUseCollationWhenPresent() { template.exists(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe(); @@ -253,7 +254,7 @@ public void existsShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findAndModfiyShoudUseCollationWhenPresent() { + void findAndModfiyShoudUseCollationWhenPresent() { when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty()); @@ -267,7 +268,7 @@ public void findAndModfiyShoudUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findAndRemoveShouldUseCollationWhenPresent() { + void findAndRemoveShouldUseCollationWhenPresent() { when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(Mono.empty()); @@ -280,7 +281,7 @@ public void findAndRemoveShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void findAndRemoveManyShouldUseCollationWhenPresent() { + void findAndRemoveManyShouldUseCollationWhenPresent() { when(collection.deleteMany(any(Bson.class), any())).thenReturn(Mono.empty()); @@ -294,7 +295,7 @@ public void findAndRemoveManyShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void updateOneShouldUseCollationWhenPresent() { + void updateOneShouldUseCollationWhenPresent() { when(collection.updateOne(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty()); @@ -308,7 +309,7 @@ public void updateOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void updateManyShouldUseCollationWhenPresent() { + void updateManyShouldUseCollationWhenPresent() { when(collection.updateMany(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty()); @@ -323,7 +324,7 @@ public void updateManyShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518 - public void replaceOneShouldUseCollationWhenPresent() { + void replaceOneShouldUseCollationWhenPresent() { when(collection.replaceOne(any(Bson.class), any(), any(ReplaceOptions.class))).thenReturn(Mono.empty()); @@ -337,7 +338,7 @@ public void replaceOneShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518, DATAMONGO-2257 - public void mapReduceShouldUseCollationWhenPresent() { + void mapReduceShouldUseCollationWhenPresent() { template.mapReduce(new BasicQuery("{}"), AutogenerateableId.class, AutogenerateableId.class, "", "", MapReduceOptions.options().collation(Collation.of("fr"))).subscribe(); @@ -346,7 +347,7 @@ public void mapReduceShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1518, DATAMONGO-2264 - public void geoNearShouldUseCollationWhenPresent() { + void geoNearShouldUseCollationWhenPresent() { NearQuery query = NearQuery.near(0D, 0D).query(new BasicQuery("{}").collation(Collation.of("fr"))); template.geoNear(query, AutogenerateableId.class).subscribe(); @@ -355,7 +356,7 @@ public void geoNearShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1719 - public void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() { + void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonProjection.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -364,7 +365,7 @@ public void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFie } @Test // DATAMONGO-1719 - public void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFields() { + void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFields() { template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, PersonProjection.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -373,7 +374,7 @@ public void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFiel } @Test // DATAMONGO-1719 - public void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { + void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonSpELProjection.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -382,7 +383,7 @@ public void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { } @Test // DATAMONGO-1719, DATAMONGO-2041 - public void appliesFieldsToDtoProjection() { + void appliesFieldsToDtoProjection() { template.doFind("star-wars", new Document(), new Document(), Person.class, Jedi.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -391,7 +392,7 @@ public void appliesFieldsToDtoProjection() { } @Test // DATAMONGO-1719 - public void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { + void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, Jedi.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -400,7 +401,7 @@ public void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { } @Test // DATAMONGO-1719 - public void doesNotApplyFieldsWhenTargetIsNotAProjection() { + void doesNotApplyFieldsWhenTargetIsNotAProjection() { template.doFind("star-wars", new Document(), new Document(), Person.class, Person.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -409,7 +410,7 @@ public void doesNotApplyFieldsWhenTargetIsNotAProjection() { } @Test // DATAMONGO-1719 - public void doesNotApplyFieldsWhenTargetExtendsDomainType() { + void doesNotApplyFieldsWhenTargetExtendsDomainType() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonExtended.class, FindPublisherPreparer.NO_OP_PREPARER).subscribe(); @@ -418,7 +419,7 @@ public void doesNotApplyFieldsWhenTargetExtendsDomainType() { } @Test // DATAMONGO-1783 - public void countShouldUseSkipFromQuery() { + void countShouldUseSkipFromQuery() { template.count(new Query().skip(10), Person.class, "star-wars").subscribe(); @@ -429,7 +430,7 @@ public void countShouldUseSkipFromQuery() { } @Test // DATAMONGO-1783 - public void countShouldUseLimitFromQuery() { + void countShouldUseLimitFromQuery() { template.count(new Query().limit(100), Person.class, "star-wars").subscribe(); @@ -440,7 +441,7 @@ public void countShouldUseLimitFromQuery() { } @Test // DATAMONGO-2360 - public void countShouldApplyQueryHintIfPresent() { + void countShouldApplyQueryHintIfPresent() { Document queryHint = new Document("age", 1); template.count(new Query().withHint(queryHint), Person.class, "star-wars").subscribe(); @@ -452,7 +453,7 @@ public void countShouldApplyQueryHintIfPresent() { } @Test // DATAMONGO-2365 - public void countShouldApplyQueryHintAsIndexNameIfPresent() { + void countShouldApplyQueryHintAsIndexNameIfPresent() { template.count(new Query().withHint("idx-1"), Person.class, "star-wars").subscribe(); @@ -463,7 +464,7 @@ public void countShouldApplyQueryHintAsIndexNameIfPresent() { } @Test // DATAMONGO-2215 - public void updateShouldApplyArrayFilters() { + void updateShouldApplyArrayFilters() { template.updateFirst(new BasicQuery("{}"), new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)), @@ -477,7 +478,7 @@ public void updateShouldApplyArrayFilters() { } @Test // DATAMONGO-2215 - public void findAndModifyShouldApplyArrayFilters() { + void findAndModifyShouldApplyArrayFilters() { template.findAndModify(new BasicQuery("{}"), new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)), @@ -491,7 +492,7 @@ public void findAndModifyShouldApplyArrayFilters() { } @Test // DATAMONGO-1854 - public void findShouldNotUseCollationWhenNoDefaultPresent() { + void findShouldNotUseCollationWhenNoDefaultPresent() { template.find(new BasicQuery("{'foo' : 'bar'}"), Jedi.class).subscribe(); @@ -499,7 +500,7 @@ public void findShouldNotUseCollationWhenNoDefaultPresent() { } @Test // DATAMONGO-1854 - public void findShouldUseDefaultCollationWhenPresent() { + void findShouldUseDefaultCollationWhenPresent() { template.find(new BasicQuery("{'foo' : 'bar'}"), Sith.class).subscribe(); @@ -507,7 +508,7 @@ public void findShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findOneShouldUseDefaultCollationWhenPresent() { + void findOneShouldUseDefaultCollationWhenPresent() { template.findOne(new BasicQuery("{'foo' : 'bar'}"), Sith.class).subscribe(); @@ -515,7 +516,7 @@ public void findOneShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void existsShouldUseDefaultCollationWhenPresent() { + void existsShouldUseDefaultCollationWhenPresent() { template.exists(new BasicQuery("{}"), Sith.class).subscribe(); @@ -523,7 +524,7 @@ public void existsShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndModfiyShoudUseDefaultCollationWhenPresent() { + void findAndModfiyShoudUseDefaultCollationWhenPresent() { template.findAndModify(new BasicQuery("{}"), new Update(), Sith.class).subscribe(); @@ -535,7 +536,7 @@ public void findAndModfiyShoudUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndRemoveShouldUseDefaultCollationWhenPresent() { + void findAndRemoveShouldUseDefaultCollationWhenPresent() { template.findAndRemove(new BasicQuery("{}"), Sith.class).subscribe(); @@ -547,7 +548,7 @@ public void findAndRemoveShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void createCollectionShouldNotCollationIfNotPresent() { + void createCollectionShouldNotCollationIfNotPresent() { template.createCollection(AutogenerateableId.class).subscribe(); @@ -558,7 +559,7 @@ public void createCollectionShouldNotCollationIfNotPresent() { } @Test // DATAMONGO-1854 - public void createCollectionShouldApplyDefaultCollation() { + void createCollectionShouldApplyDefaultCollation() { template.createCollection(Sith.class).subscribe(); @@ -570,7 +571,7 @@ public void createCollectionShouldApplyDefaultCollation() { } @Test // DATAMONGO-1854 - public void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { + void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { template.createCollection(Sith.class, CollectionOptions.just(Collation.of("en_US"))).subscribe(); @@ -582,7 +583,7 @@ public void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull() { + void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull() { template.createCollection(Sith.class, null).subscribe(); @@ -594,7 +595,7 @@ public void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull( } @Test // DATAMONGO-1854 - public void aggreateShouldUseDefaultCollationIfPresent() { + void aggreateShouldUseDefaultCollationIfPresent() { template.aggregate(newAggregation(Sith.class, project("id")), AutogenerateableId.class, Document.class).subscribe(); @@ -602,7 +603,7 @@ public void aggreateShouldUseDefaultCollationIfPresent() { } @Test // DATAMONGO-1854 - public void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { + void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { template .aggregate( @@ -615,7 +616,7 @@ public void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent } @Test // DATAMONGO-2153 - public void aggregateShouldHonorOptionsComment() { + void aggregateShouldHonorOptionsComment() { AggregationOptions options = AggregationOptions.builder().comment("expensive").build(); @@ -626,7 +627,7 @@ public void aggregateShouldHonorOptionsComment() { } @Test // DATAMONGO-2390 - public void aggregateShouldNoApplyZeroOrNegativeMaxTime() { + void aggregateShouldNoApplyZeroOrNegativeMaxTime() { template .aggregate(newAggregation(MongoTemplateUnitTests.Sith.class, project("id")).withOptions( @@ -643,7 +644,7 @@ public void aggregateShouldNoApplyZeroOrNegativeMaxTime() { } @Test // DATAMONGO-2390 - public void aggregateShouldApplyMaxTimeIfSet() { + void aggregateShouldApplyMaxTimeIfSet() { template .aggregate( @@ -656,7 +657,7 @@ public void aggregateShouldApplyMaxTimeIfSet() { } @Test // DATAMONGO-1854 - public void findAndReplaceShouldUseCollationWhenPresent() { + void findAndReplaceShouldUseCollationWhenPresent() { template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new Jedi()).subscribe(); @@ -667,7 +668,7 @@ public void findAndReplaceShouldUseCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndReplaceShouldUseDefaultCollationWhenPresent() { + void findAndReplaceShouldUseDefaultCollationWhenPresent() { template.findAndReplace(new BasicQuery("{}"), new Sith()).subscribe(); @@ -678,7 +679,7 @@ public void findAndReplaceShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { + void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new MongoTemplateUnitTests.Sith()) .subscribe(); @@ -690,7 +691,7 @@ public void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { } @Test // DATAMONGO-1854 - public void findDistinctShouldUseDefaultCollationWhenPresent() { + void findDistinctShouldUseDefaultCollationWhenPresent() { template.findDistinct(new BasicQuery("{}"), "name", Sith.class, String.class).subscribe(); @@ -698,7 +699,7 @@ public void findDistinctShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void findDistinctPreferCollationFromQueryOverDefaultCollation() { + void findDistinctPreferCollationFromQueryOverDefaultCollation() { template.findDistinct(new BasicQuery("{}").collation(Collation.of("fr")), "name", Sith.class, String.class) .subscribe(); @@ -707,7 +708,7 @@ public void findDistinctPreferCollationFromQueryOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void updateFirstShouldUseDefaultCollationWhenPresent() { + void updateFirstShouldUseDefaultCollationWhenPresent() { template.updateFirst(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class).subscribe(); @@ -719,7 +720,7 @@ public void updateFirstShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { + void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { template.updateFirst(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class) .subscribe(); @@ -732,7 +733,7 @@ public void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void updateMultiShouldUseDefaultCollationWhenPresent() { + void updateMultiShouldUseDefaultCollationWhenPresent() { template.updateMulti(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class).subscribe(); @@ -744,7 +745,7 @@ public void updateMultiShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { + void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { template.updateMulti(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class) .subscribe(); @@ -757,7 +758,7 @@ public void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-1854 - public void removeShouldUseDefaultCollationWhenPresent() { + void removeShouldUseDefaultCollationWhenPresent() { template.remove(new BasicQuery("{}"), Sith.class).subscribe(); @@ -769,7 +770,7 @@ public void removeShouldUseDefaultCollationWhenPresent() { } @Test // DATAMONGO-1854 - public void removeShouldPreferExplicitCollationOverDefaultCollation() { + void removeShouldPreferExplicitCollationOverDefaultCollation() { template.remove(new BasicQuery("{}").collation(Collation.of("fr")), Sith.class).subscribe(); @@ -781,7 +782,7 @@ public void removeShouldPreferExplicitCollationOverDefaultCollation() { } @Test // DATAMONGO-2261 - public void saveShouldInvokeCallbacks() { + void saveShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -799,7 +800,7 @@ public void saveShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void insertShouldInvokeCallbacks() { + void insertShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -817,7 +818,7 @@ public void insertShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void insertAllShouldInvokeCallbacks() { + void insertAllShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -839,7 +840,7 @@ public void insertAllShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void findAndReplaceShouldInvokeCallbacks() { + void findAndReplaceShouldInvokeCallbacks() { ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); @@ -857,12 +858,12 @@ public void findAndReplaceShouldInvokeCallbacks() { } @Test // DATAMONGO-2261 - public void entityCallbacksAreNotSetByDefault() { + void entityCallbacksAreNotSetByDefault() { Assertions.assertThat(ReflectionTestUtils.getField(template, "entityCallbacks")).isNull(); } @Test // DATAMONGO-2261 - public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { + void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { ApplicationContext ctx = new StaticApplicationContext(); template.setApplicationContext(ctx); @@ -871,7 +872,7 @@ public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { } @Test // DATAMONGO-2261 - public void setterForEntityCallbackOverridesContextInitializedOnes() { + void setterForEntityCallbackOverridesContextInitializedOnes() { ApplicationContext ctx = new StaticApplicationContext(); template.setApplicationContext(ctx); @@ -883,7 +884,7 @@ public void setterForEntityCallbackOverridesContextInitializedOnes() { } @Test // DATAMONGO-2261 - public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { + void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { ReactiveEntityCallbacks callbacks = ReactiveEntityCallbacks.create(); ApplicationContext ctx = new StaticApplicationContext(); @@ -895,7 +896,7 @@ public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallback } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { template.find(new Query().slaveOk(), AutogenerateableId.class).subscribe(); @@ -903,7 +904,7 @@ public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { template.findOne(new Query().slaveOk(), AutogenerateableId.class).subscribe(); @@ -911,7 +912,7 @@ public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOn } @Test // DATAMONGO-2344 - public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { + void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { template.findDistinct(new Query().slaveOk(), "name", AutogenerateableId.class, String.class).subscribe(); @@ -919,7 +920,7 @@ public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDi } @Test // DATAMONGO-2331 - public void updateShouldAllowAggregationExpressions() { + void updateShouldAllowAggregationExpressions() { AggregationUpdate update = AggregationUpdate.update().set("total") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); @@ -935,7 +936,7 @@ public void updateShouldAllowAggregationExpressions() { } @Test // DATAMONGO-2331 - public void updateShouldAllowMultipleAggregationExpressions() { + void updateShouldAllowMultipleAggregationExpressions() { AggregationUpdate update = AggregationUpdate.update() // .set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) // @@ -963,7 +964,7 @@ public void updateShouldAllowMultipleAggregationExpressions() { } @Test // DATAMONGO-2331 - public void updateShouldMapAggregationExpressionToDomainType() { + void updateShouldMapAggregationExpressionToDomainType() { AggregationUpdate update = AggregationUpdate.update().set("name") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); @@ -979,7 +980,7 @@ public void updateShouldMapAggregationExpressionToDomainType() { } @Test // DATAMONGO-2331 - public void updateShouldPassOnUnsetCorrectly() { + void updateShouldPassOnUnsetCorrectly() { SetOperation setOperation = SetOperation.builder().set("status").toValue("Modified").and().set("comments") .toValue(Fields.fields("misc1").and("misc2").asList()); @@ -999,7 +1000,7 @@ public void updateShouldPassOnUnsetCorrectly() { } @Test // DATAMONGO-2331 - public void updateShouldMapAggregationUnsetToDomainType() { + void updateShouldMapAggregationUnsetToDomainType() { AggregationUpdate update = AggregationUpdate.update(); update.unset("name"); @@ -1110,163 +1111,138 @@ void saveVersionedShouldProjectOnShardKeyWhenLoadingExistingDocument() { } @Test // DATAMONGO-2479 - public void findShouldInvokeAfterConvertCallbacks() { + void findShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.find(Document.class)).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); - List results = template.find(new Query(), Person.class).timeout(Duration.ofSeconds(1)) - .toStream().collect(Collectors.toList()); + List results = template.find(new Query(), Person.class).timeout(Duration.ofSeconds(1)).toStream() + .collect(Collectors.toList()); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(results.get(0).id).isEqualTo("after-convert"); } - private Document initialLukeDocument() { - return new Document(ImmutableMap.of( - "_id", "init", - "firstname", "luke" - )); - } - - private Person initialLuke() { - Person expectedEnitty = new Person(); - expectedEnitty.id = "init"; - expectedEnitty.firstname = "luke"; - return expectedEnitty; - } - @Test // DATAMONGO-2479 - public void findByIdShouldInvokeAfterConvertCallbacks() { + void findByIdShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); Person result = template.findById("init", Person.class).block(Duration.ofSeconds(1)); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(result.id).isEqualTo("after-convert"); } @Test // DATAMONGO-2479 - public void findOneShouldInvokeAfterConvertCallbacks() { + void findOneShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); Person result = template.findOne(new Query(), Person.class).block(Duration.ofSeconds(1)); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(result.id).isEqualTo("after-convert"); } @Test // DATAMONGO-2479 - public void findAllShouldInvokeAfterConvertCallbacks() { + void findAllShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.find(Document.class)).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); - List results = template.findAll(Person.class).timeout(Duration.ofSeconds(1)) - .toStream().collect(Collectors.toList()); + List results = template.findAll(Person.class).timeout(Duration.ofSeconds(1)).toStream() + .collect(Collectors.toList()); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(results.get(0).id).isEqualTo("after-convert"); } @Test // DATAMONGO-2479 - public void findAndModifyShouldInvokeAfterConvertCallbacks() { + void findAndModifyShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); Person result = template.findAndModify(new Query(), new Update(), Person.class).block(Duration.ofSeconds(1)); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(result.id).isEqualTo("after-convert"); } @Test // DATAMONGO-2479 - public void findAndRemoveShouldInvokeAfterConvertCallbacks() { + void findAndRemoveShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); Person result = template.findAndRemove(new Query(), Person.class).block(Duration.ofSeconds(1)); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(result.id).isEqualTo("after-convert"); } @Test // DATAMONGO-2479 - public void findAllAndRemoveShouldInvokeAfterConvertCallbacks() { + void findAllAndRemoveShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.find(Document.class)).thenReturn(findPublisher); - makeFindPublisherPublishJust(document); + stubFindSubscribe(document); when(collection.deleteMany(any(Bson.class), any(DeleteOptions.class))) .thenReturn(Mono.just(spy(DeleteResult.class))); List results = template.findAllAndRemove(new Query(), Person.class).timeout(Duration.ofSeconds(1)) .toStream().collect(Collectors.toList()); - verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); + verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString()); assertThat(results.get(0).id).isEqualTo("after-convert"); } - private void makeFindPublisherPublishJust(Document document) { - - Publisher realPublisher = Flux.just(document); - - doAnswer(invocation -> { - Subscriber subscriber = invocation.getArgument(0); - realPublisher.subscribe(subscriber); - return null; - }).when(findPublisher).subscribe(any()); - } - @Test // DATAMONGO-2479 - public void findAndReplaceShouldInvokeAfterConvertCallbacks() { + void findAndReplaceShouldInvokeAfterConvertCallbacks() { ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher); - makeFindPublisherPublishJust(initialLukeDocument()); + stubFindSubscribe(new Document("_id", "init").append("firstname", "luke")); Person entity = new Person(); entity.id = "init"; @@ -1279,7 +1255,7 @@ public void findAndReplaceShouldInvokeAfterConvertCallbacks() { } @Test // DATAMONGO-2479 - public void saveShouldInvokeAfterSaveCallbacks() { + void saveShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); @@ -1288,7 +1264,7 @@ public void saveShouldInvokeAfterSaveCallbacks() { when(collection.replaceOne(any(Bson.class), any(Document.class), any(ReplaceOptions.class))) .thenReturn(Mono.just(mock(UpdateResult.class))); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); Person saved = template.save(entity).block(Duration.ofSeconds(1)); @@ -1297,7 +1273,7 @@ public void saveShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void insertShouldInvokeAfterSaveCallbacks() { + void insertShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); @@ -1305,7 +1281,7 @@ public void insertShouldInvokeAfterSaveCallbacks() { when(collection.insertOne(any())).thenReturn(Mono.just(mock(InsertOneResult.class))); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); Person saved = template.insert(entity).block(Duration.ofSeconds(1)); @@ -1314,7 +1290,7 @@ public void insertShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void insertAllShouldInvokeAfterSaveCallbacks() { + void insertAllShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); @@ -1333,9 +1309,8 @@ public void insertAllShouldInvokeAfterSaveCallbacks() { return Flux.fromIterable(list).map(i -> mock(InsertManyResult.class)); }); - List saved = template.insertAll(Arrays.asList(entity1, entity2)) - .timeout(Duration.ofSeconds(1)) - .toStream().collect(Collectors.toList()); + List saved = template.insertAll(Arrays.asList(entity1, entity2)).timeout(Duration.ofSeconds(1)).toStream() + .collect(Collectors.toList()); verify(afterSaveCallback, times(2)).onAfterSave(any(), any(), anyString()); assertThat(saved.get(0).id).isEqualTo("after-save"); @@ -1343,16 +1318,16 @@ public void insertAllShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void findAndReplaceShouldInvokeAfterSaveCallbacks() { + void findAndReplaceShouldInvokeAfterSaveCallbacks() { ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher); - makeFindPublisherPublishJust(initialLukeDocument()); + stubFindSubscribe(new Document("_id", "init").append("firstname", "luke")); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); @@ -1361,7 +1336,7 @@ public void findAndReplaceShouldInvokeAfterSaveCallbacks() { } @Test // DATAMONGO-2479 - public void findAndReplaceShouldEmitAfterSaveEvent() { + void findAndReplaceShouldEmitAfterSaveEvent() { AbstractMongoEventListener eventListener = new AbstractMongoEventListener() { @@ -1379,9 +1354,9 @@ public void onAfterSave(AfterSaveEvent event) { template.setApplicationContext(ctx); - Person entity = initialLuke(); + Person entity = new Person("init", "luke"); - Document document = initialLukeDocument(); + Document document = new Document("_id", "init").append("firstname", "luke"); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(Mono.just(document)); Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); @@ -1389,8 +1364,21 @@ public void onAfterSave(AfterSaveEvent event) { assertThat(saved.id).isEqualTo("after-save-event"); } + private void stubFindSubscribe(Document document) { + + Publisher realPublisher = Flux.just(document); + + doAnswer(invocation -> { + Subscriber subscriber = invocation.getArgument(0); + realPublisher.subscribe(subscriber); + return null; + }).when(findPublisher).subscribe(any()); + } + @Data @org.springframework.data.mongodb.core.mapping.Document(collection = "star-wars") + @AllArgsConstructor + @NoArgsConstructor static class Person { @Id String id; @@ -1472,7 +1460,7 @@ public Mono onBeforeSave(Person entity, Document document, String collec return Mono.just(entity); } } - + static class ValueCapturingAfterConvertCallback extends ValueCapturingEntityCallback implements ReactiveAfterConvertCallback { @@ -1480,10 +1468,12 @@ static class ValueCapturingAfterConvertCallback extends ValueCapturingEntityCall public Mono onAfterConvert(Person entity, Document document, String collection) { capture(entity); - return Mono.just(new Person() {{ - id = "after-convert"; - firstname = entity.firstname; - }}); + return Mono.just(new Person() { + { + id = "after-convert"; + firstname = entity.firstname; + } + }); } } @@ -1494,10 +1484,12 @@ static class ValueCapturingAfterSaveCallback extends ValueCapturingEntityCallbac public Mono onAfterSave(Person entity, Document document, String collection) { capture(entity); - return Mono.just(new Person() {{ - id = "after-save"; - firstname = entity.firstname; - }}); + return Mono.just(new Person() { + { + id = "after-save"; + firstname = entity.firstname; + } + }); } } diff --git a/src/main/asciidoc/reference/mongo-entity-callbacks.adoc b/src/main/asciidoc/reference/mongo-entity-callbacks.adoc index 7576a17347..3bb2a34ead 100644 --- a/src/main/asciidoc/reference/mongo-entity-callbacks.adoc +++ b/src/main/asciidoc/reference/mongo-entity-callbacks.adoc @@ -16,6 +16,12 @@ Spring Data MongoDB uses the `EntityCallback` API for its auditing support and r | Invoked before a domain object is converted to `org.bson.Document`. | `Ordered.LOWEST_PRECEDENCE` +| Reactive/AfterConvertCallback +| `onAfterConvert(T entity, org.bson.Document target, String collection)` +| Invoked after a domain object is loaded. + +Can modify the domain object after reading it from a `org.bson.Document`. +| `Ordered.LOWEST_PRECEDENCE` + | Reactive/AuditingEntityCallback | `onBeforeConvert(Object entity, String collection)` | Marks an auditable entity _created_ or _modified_ @@ -27,5 +33,11 @@ Spring Data MongoDB uses the `EntityCallback` API for its auditing support and r Can modify the target, to be persisted, `Document` containing all mapped entity information. | `Ordered.LOWEST_PRECEDENCE` +| Reactive/AfterSaveCallback +| `onAfterSave(T entity, org.bson.Document target, String collection)` +| Invoked before a domain object is saved. + + Can modify the domain object, to be returned after save, `Document` containing all mapped entity information. +| `Ordered.LOWEST_PRECEDENCE` + |=== From 5fb4b036bb05f09d4c920aaf8f0f6bd0455436d0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 17 Mar 2020 10:57:15 +0100 Subject: [PATCH 0109/1381] DATAMONGO-1026 - Include documentation about custom conversions. We now include the documentations partial about custom conversions that explains default converter registrations, overrides and system setting timezone-sensitivity. --- src/main/asciidoc/reference/mapping.adoc | 43 +------------- .../reference/mongo-custom-conversions.adoc | 59 ++----------------- src/main/asciidoc/reference/mongodb.adoc | 2 - 3 files changed, 6 insertions(+), 98 deletions(-) diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 35d7b83876..48eee558da 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -771,45 +771,4 @@ Events are fired throughout the lifecycle of the mapping process. This is descri Declaring these beans in your Spring ApplicationContext causes them to be invoked whenever the event is dispatched. -[[mapping-explicit-converters]] -=== Overriding Mapping with Explicit Converters - -When storing and querying your objects, it is convenient to have a `MongoConverter` instance handle the mapping of all Java types to `Document` instances. However, sometimes you may want the `MongoConverter` instances do most of the work but let you selectively handle the conversion for a particular type -- perhaps to optimize performance. - -To selectively handle the conversion yourself, register one or more one or more `org.springframework.core.convert.converter.Converter` instances with the `MongoConverter`. - -NOTE: Spring 3.0 introduced a core.convert package that provides a general type conversion system. This is described in detail in the Spring reference documentation section entitled https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#validation["`Spring Type Conversion`"]. - -You can use the `customConversions` method in `AbstractMongoClientConfiguration` to configure converters. The examples <> show how to perform the configuration using Java and XML. - -The following example of a Spring Converter implementation converts from a `Document` to a `Person` POJO: - -[source,java] ----- -@ReadingConverter - public class PersonReadConverter implements Converter { - - public Person convert(Document source) { - Person p = new Person((ObjectId) source.get("_id"), (String) source.get("name")); - p.setAge((Integer) source.get("age")); - return p; - } -} ----- - -The following example converts from a `Person` to a `Document`: - -[source,java] ----- -@WritingConverter -public class PersonWriteConverter implements Converter { - - public Document convert(Person source) { - Document document = new Document(); - document.put("_id", source.getId()); - document.put("name", source.getFirstName()); - document.put("age", source.getAge()); - return document; - } -} ----- +include::mongo-custom-conversions.adoc[] diff --git a/src/main/asciidoc/reference/mongo-custom-conversions.adoc b/src/main/asciidoc/reference/mongo-custom-conversions.adoc index c4707f389c..0032487551 100644 --- a/src/main/asciidoc/reference/mongo-custom-conversions.adoc +++ b/src/main/asciidoc/reference/mongo-custom-conversions.adoc @@ -1,7 +1,7 @@ [[mongo.custom-converters]] == 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 +The most trivial way of influencing 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 values in native `org.bson.types.Decimal128` format. @@ -101,60 +101,11 @@ class MyMongoConfiguration extends AbstractMongoClientConfiguration { } @Override - public CustomConversions customConversions() { - - List> converters = new ArrayList<>(2); - converters.add(new com.example.PersonReadConverter()); - converters.add(new com.example.PersonWriteConverter()); - return new MongoCustomConversions(converters); + protected void configureConverters(MongoConverterConfigurationAdapter adapter) { + adapter.registerConverter(new com.example.PersonReadConverter()); + adapter.registerConverter(new com.example.PersonWriteConverter()); } } ---- -The Mongo Spring namespace provides a convenient way to register Spring `Converter` instances with the `MappingMongoConverter`. The following configuration snippet shows how to manually register converter beans as well as configure the wrapping `MappingMongoConverter` into a `MongoTemplate`: - -[source,xml] ----- - - - - - - - - - - - - - - - - - ----- - -You can also use the `base-package` attribute of the `custom-converters` element to enable classpath scanning for all `Converter` and `GenericConverter` implementations below the given package, as the following example shows: - -[source,xml] ----- - - - ----- - -[[mongo.converter-disambiguation]] -=== Converter Disambiguation - -Generally, we inspect the `Converter` implementations for the source and target types they convert from and to. Depending on whether one of those is a type MongoDB can handle natively, we register the converter instance as a reading or a writing converter. The following examples show a writer converter and a read converter (note the difference is in the order of the qualifiers on `Converter`): - -[source,java] ----- -// Write converter as only the target type is one Mongo can handle natively -class MyConverter implements Converter { … } - -// Read converter as only the source type is one Mongo can handle natively -class MyConverter implements Converter { … } ----- - -If you write a `Converter` whose source and target type are native Mongo types, we cannot determine whether we should consider it as a reading or a writing converter. Registering the converter instance as both might lead to unwanted results. For example, a `Converter` is ambiguous, although it probably does not make sense to try to convert all `String` instances into `Long` instances when writing. To let you force the infrastructure to register a converter for only one way, we provide `@ReadingConverter` and `@WritingConverter` annotations to be used in the converter implementation. +include::../{spring-data-commons-docs}/custom-conversions.adoc[leveloffset=+3] diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 7d849dfe13..a29aefe768 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -3072,8 +3072,6 @@ TypedAggregation agg = Aggregation.newAggregation(Book.class, <4> Otherwise, add the field value of `author.middle`. ==== -include::mongo-custom-conversions.adoc[leveloffset=+1] - [[mongo-template.index-and-collections]] == Index and Collection Management From 6387eb97620350a9e419d4457d18e1cf295d3d43 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 10 Mar 2020 14:44:38 +0100 Subject: [PATCH 0110/1381] DATAMONGO-2416 - Add convenience methods accepting CriteriaDefinition on Fluent API. The fluent API now exposes default interface methods accepting CriteriaDefinition for a more concise expression of queries that do not require a Query object. template.query(Person.class).matching(where("firstname").is("luke")).all() instead of template.query(Person.class).matching(query(where("firstname").is("luke"))).all() Original Pull Request: #840 --- .../mongodb/core/ExecutableFindOperation.java | 13 +++++++++++++ .../core/ExecutableMapReduceOperation.java | 16 +++++++++++++++- .../mongodb/core/ExecutableRemoveOperation.java | 13 +++++++++++++ .../mongodb/core/ExecutableUpdateOperation.java | 13 +++++++++++++ .../mongodb/core/ReactiveFindOperation.java | 13 +++++++++++++ .../core/ReactiveMapReduceOperation.java | 15 ++++++++++++++- .../mongodb/core/ReactiveRemoveOperation.java | 13 +++++++++++++ .../mongodb/core/ReactiveUpdateOperation.java | 17 +++++++++++++++-- .../data/mongodb/core/query/Query.java | 2 ++ .../ExecutableFindOperationSupportTests.java | 5 +++++ ...tableMapReduceOperationSupportUnitTests.java | 14 ++++++++++++++ .../ExecutableRemoveOperationSupportTests.java | 8 ++++++++ .../ExecutableUpdateOperationSupportTests.java | 11 +++++++++++ .../core/ReactiveFindOperationSupportTests.java | 8 ++++++++ ...ctiveMapReduceOperationSupportUnitTests.java | 15 +++++++++++++++ .../ReactiveRemoveOperationSupportTests.java | 7 +++++++ .../ReactiveUpdateOperationSupportTests.java | 11 +++++++++++ .../query/AbstractMongoQueryUnitTests.java | 2 +- .../AbstractReactiveMongoQueryUnitTests.java | 5 ++++- 19 files changed, 195 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index 9bf2246b95..86ed2e52ff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -21,6 +21,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.data.geo.GeoResults; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.lang.Nullable; @@ -170,6 +171,18 @@ interface FindWithQuery extends TerminatingFind { */ TerminatingFind matching(Query query); + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteriaDefinition must not be {@literal null}. + * @return new instance of {@link TerminatingFind}. + * @throws IllegalArgumentException if query is {@literal null}. + * @since 3.0 + */ + default TerminatingFind matching(CriteriaDefinition criteriaDefinition) { + return matching(Query.query(criteriaDefinition)); + } + /** * Set the filter query for the geoNear execution. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java index 877295f815..73ecb66bed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java @@ -19,6 +19,7 @@ import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.Query; /** @@ -30,7 +31,7 @@ * The collection to operate on is by default derived from the initial {@literal domainType} and can be defined there * via {@link org.springframework.data.mongodb.core.mapping.Document}. Using {@code inCollection} allows to override the * collection name for the execution. - * + * *

        *     
        *         mapReduce(Human.class)
      @@ -44,6 +45,7 @@
        * 
      * * @author Christoph Strobl + * @author Mark Paluch * @since 2.1 */ public interface ExecutableMapReduceOperation { @@ -146,6 +148,18 @@ interface MapReduceWithQuery extends TerminatingMapReduce { * @throws IllegalArgumentException if query is {@literal null}. */ TerminatingMapReduce matching(Query query); + + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteriaDefinition must not be {@literal null}. + * @return new instance of {@link TerminatingMapReduce}. + * @throws IllegalArgumentException if query is {@literal null}. + * @since 3.0 + */ + default TerminatingMapReduce matching(CriteriaDefinition criteriaDefinition) { + return matching(Query.query(criteriaDefinition)); + } } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java index eb031c0353..5f4fb8d9d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java @@ -17,6 +17,7 @@ import java.util.List; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.result.DeleteResult; @@ -119,6 +120,18 @@ interface RemoveWithQuery extends TerminatingRemove { * @throws IllegalArgumentException if query is {@literal null}. */ TerminatingRemove matching(Query query); + + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteriaDefinition must not be {@literal null}. + * @return new instance of {@link TerminatingRemove}. + * @throws IllegalArgumentException if query is {@literal null}. + * @since 3.0 + */ + default TerminatingRemove matching(CriteriaDefinition criteriaDefinition) { + return matching(Query.query(criteriaDefinition)); + } } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index 7155551b86..b3c9b084a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.UpdateDefinition; @@ -210,6 +211,18 @@ interface UpdateWithQuery extends UpdateWithUpdate { * @throws IllegalArgumentException if query is {@literal null}. */ UpdateWithUpdate matching(Query query); + + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteriaDefinition must not be {@literal null}. + * @return new instance of {@link UpdateWithUpdate}. + * @throws IllegalArgumentException if query is {@literal null}. + * @since 3.0 + */ + default UpdateWithUpdate matching(CriteriaDefinition criteriaDefinition) { + return matching(Query.query(criteriaDefinition)); + } } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index 793c73a11c..a96c6b1062 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -19,6 +19,7 @@ import reactor.core.publisher.Mono; import org.springframework.data.geo.GeoResult; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; @@ -144,6 +145,18 @@ interface FindWithQuery extends TerminatingFind { */ TerminatingFind matching(Query query); + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteriaDefinition must not be {@literal null}. + * @return new instance of {@link TerminatingFind}. + * @throws IllegalArgumentException if query is {@literal null}. + * @since 3.0 + */ + default TerminatingFind matching(CriteriaDefinition criteriaDefinition) { + return matching(Query.query(criteriaDefinition)); + } + /** * Set the filter query for the geoNear execution. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java index 20d22204ac..12f71eb24d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java @@ -19,6 +19,7 @@ import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.Query; /** @@ -30,7 +31,7 @@ * The collection to operate on is by default derived from the initial {@literal domainType} and can be defined there * via {@link org.springframework.data.mongodb.core.mapping.Document}. Using {@code inCollection} allows to override the * collection name for the execution. - * + * *
        *     
        *         mapReduce(Human.class)
      @@ -146,6 +147,18 @@ interface MapReduceWithQuery extends TerminatingMapReduce {
       		 * @throws IllegalArgumentException if query is {@literal null}.
       		 */
       		TerminatingMapReduce matching(Query query);
      +
      +		/**
      +		 * Set the filter {@link CriteriaDefinition criteria} to be used.
      +		 *
      +		 * @param criteriaDefinition must not be {@literal null}.
      +		 * @return new instance of {@link TerminatingMapReduce}.
      +		 * @throws IllegalArgumentException if query is {@literal null}.
      +		 * @since 3.0
      +		 */
      +		default TerminatingMapReduce matching(CriteriaDefinition criteriaDefinition) {
      +			return matching(Query.query(criteriaDefinition));
      +		}
       	}
       
       	/**
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java
      index 1e51dec359..f3c3421e32 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java
      @@ -18,6 +18,7 @@
       import reactor.core.publisher.Flux;
       import reactor.core.publisher.Mono;
       
      +import org.springframework.data.mongodb.core.query.CriteriaDefinition;
       import org.springframework.data.mongodb.core.query.Query;
       
       import com.mongodb.client.result.DeleteResult;
      @@ -106,6 +107,18 @@ interface RemoveWithQuery extends TerminatingRemove {
       		 * @throws IllegalArgumentException if query is {@literal null}.
       		 */
       		TerminatingRemove matching(Query query);
      +
      +		/**
      +		 * Set the filter {@link CriteriaDefinition criteria} to be used.
      +		 *
      +		 * @param criteriaDefinition must not be {@literal null}.
      +		 * @return new instance of {@link TerminatingRemove}.
      +		 * @throws IllegalArgumentException if query is {@literal null}.
      +		 * @since 3.0
      +		 */
      +		default TerminatingRemove matching(CriteriaDefinition criteriaDefinition) {
      +			return matching(Query.query(criteriaDefinition));
      +		}
       	}
       
       	interface ReactiveRemove extends RemoveWithCollection {}
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java
      index 0bb6d23c00..cb8c154b07 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java
      @@ -15,12 +15,13 @@
        */
       package org.springframework.data.mongodb.core;
       
      -import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
      -import org.springframework.data.mongodb.core.query.UpdateDefinition;
       import reactor.core.publisher.Mono;
       
      +import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
      +import org.springframework.data.mongodb.core.query.CriteriaDefinition;
       import org.springframework.data.mongodb.core.query.Query;
       import org.springframework.data.mongodb.core.query.Update;
      +import org.springframework.data.mongodb.core.query.UpdateDefinition;
       
       import com.mongodb.client.result.UpdateResult;
       
      @@ -171,6 +172,18 @@ interface UpdateWithQuery extends UpdateWithUpdate {
       		 * @throws IllegalArgumentException if query is {@literal null}.
       		 */
       		UpdateWithUpdate matching(Query query);
      +
      +		/**
      +		 * Set the filter {@link CriteriaDefinition criteria} to be used.
      +		 *
      +		 * @param criteriaDefinition must not be {@literal null}.
      +		 * @return new instance of {@link UpdateWithUpdate}.
      +		 * @throws IllegalArgumentException if query is {@literal null}.
      +		 * @since 3.0
      +		 */
      +		default UpdateWithUpdate matching(CriteriaDefinition criteriaDefinition) {
      +			return matching(Query.query(criteriaDefinition));
      +		}
       	}
       
       	/**
      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 32a08431dc..154d5de591 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
      @@ -95,6 +95,8 @@ public Query(CriteriaDefinition criteriaDefinition) {
       	 */
       	public Query addCriteria(CriteriaDefinition criteriaDefinition) {
       
      +		Assert.notNull(criteriaDefinition, "CriteriaDefinition must not be null!");
      +
       		CriteriaDefinition existing = this.criteria.get(criteriaDefinition.getKey());
       		String key = criteriaDefinition.getKey();
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
      index 0a0e3e04f3..779f59866d 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
      @@ -169,6 +169,11 @@ public void findBy() {
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).one()).contains(luke);
       	}
       
      +	@Test // DATAMONGO-2416
      +	public void findByCriteria() {
      +		assertThat(template.query(Person.class).matching(where("firstname").is("luke")).one()).contains(luke);
      +	}
      +
       	@Test // DATAMONGO-1563
       	public void findByNoMatch() {
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("spock"))).one()).isEmpty();
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java
      index 6bc43225ff..bca48a3465 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java
      @@ -18,6 +18,7 @@
       import static org.assertj.core.api.Assertions.*;
       import static org.mockito.ArgumentMatchers.*;
       import static org.mockito.Mockito.*;
      +import static org.springframework.data.mongodb.core.query.Criteria.*;
       
       import lombok.AllArgsConstructor;
       import lombok.Data;
      @@ -39,6 +40,7 @@
        * Unit tests for {@link ExecutableMapReduceOperationSupport}.
        *
        * @author Christoph Strobl
      + * @author Mark Paluch
        * @currentRead Beyond the Shadows - Brent Weeks
        */
       @ExtendWith(MockitoExtension.class)
      @@ -109,6 +111,18 @@ void usesQueryWhenPresent() {
       				isNull(), eq(Person.class));
       	}
       
      +	@Test // DATAMONGO-2416
      +	void usesCriteriaWhenPresent() {
      +
      +		when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS);
      +		Query query = Query.query(where("lastname").is("skywalker"));
      +		mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION)
      +				.matching(where("lastname").is("skywalker")).all();
      +
      +		verify(template).mapReduce(eq(query), eq(Person.class), eq(STAR_WARS), eq(MAP_FUNCTION), eq(REDUCE_FUNCTION),
      +				isNull(), eq(Person.class));
      +	}
      +
       	@Test // DATAMONGO-1929
       	void usesProjectionWhenPresent() {
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java
      index cec119d49c..52ce526e9a 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java
      @@ -84,6 +84,14 @@ public void removeAllMatching() {
       		assertThat(result.getDeletedCount()).isEqualTo(1L);
       	}
       
      +	@Test // DATAMONGO-2416
      +	public void removeAllMatchingCriteria() {
      +
      +		DeleteResult result = template.remove(Person.class).matching(where("firstname").is("han")).all();
      +
      +		assertThat(result.getDeletedCount()).isEqualTo(1L);
      +	}
      +
       	@Test // DATAMONGO-1563
       	public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java
      index 712c5ce027..2c5196003d 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java
      @@ -120,6 +120,17 @@ public void updateAllMatching() {
       		assertThat(result.getUpsertedId()).isNull();
       	}
       
      +	@Test // DATAMONGO-2416
      +	public void updateAllMatchingCriteria() {
      +
      +		UpdateResult result = template.update(Person.class).matching(where("id").is(han.getId()))
      +				.apply(new Update().set("firstname", "Han"))
      +				.all();
      +
      +		assertThat(result.getModifiedCount()).isEqualTo(1L);
      +		assertThat(result.getUpsertedId()).isNull();
      +	}
      +
       	@Test // DATAMONGO-1563
       	public void updateWithDifferentDomainClassAndCollection() {
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java
      index 1b5d2127e4..70a0975a5c 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java
      @@ -163,6 +163,14 @@ public void findAllBy() {
       				.verifyComplete();
       	}
       
      +	@Test // DATAMONGO-2416
      +	public void findAllByCriteria() {
      +
      +		template.query(Person.class).matching(where("firstname").is("luke")).all().as(StepVerifier::create) //
      +				.expectNext(luke) //
      +				.verifyComplete();
      +	}
      +
       	@Test // DATAMONGO-1719
       	public void findAllByWithCollectionUsingMappingInformation() {
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java
      index 07e0b743bb..98ce6d5e6c 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupportUnitTests.java
      @@ -18,6 +18,7 @@
       import static org.assertj.core.api.Assertions.*;
       import static org.mockito.ArgumentMatchers.*;
       import static org.mockito.Mockito.*;
      +import static org.springframework.data.mongodb.core.query.Criteria.*;
       
       import lombok.AllArgsConstructor;
       import lombok.Data;
      @@ -39,6 +40,7 @@
        * Unit tests for {@link ReactiveMapReduceOperationSupport}.
        *
        * @author Christoph Strobl
      + * @author Mark Paluch
        * @currentRead Beyond the Shadows - Brent Weeks
        */
       @ExtendWith(MockitoExtension.class)
      @@ -112,6 +114,19 @@ void usesQueryWhenPresent() {
       				eq(REDUCE_FUNCTION), isNull());
       	}
       
      +	@Test // DATAMONGO-2416
      +	void usesCriteriaWhenPresent() {
      +
      +		when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS);
      +
      +		Query query = Query.query(where("lastname").is("skywalker"));
      +		mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION)
      +				.matching(where("lastname").is("skywalker")).all();
      +
      +		verify(template).mapReduce(eq(query), eq(Person.class), eq(STAR_WARS), eq(Person.class), eq(MAP_FUNCTION),
      +				eq(REDUCE_FUNCTION), isNull());
      +	}
      +
       	@Test // DATAMONGO-1929
       	void usesProjectionWhenPresent() {
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java
      index 7b0d30c193..efd8d5a7fb 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java
      @@ -85,6 +85,13 @@ public void removeAllMatching() {
       				.consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L)).verifyComplete();
       	}
       
      +	@Test // DATAMONGO-1719
      +	public void removeAllMatchingCriteria() {
      +
      +		template.remove(Person.class).matching(where("firstname").is("han")).all().as(StepVerifier::create)
      +				.consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L)).verifyComplete();
      +	}
      +
       	@Test // DATAMONGO-1719
       	public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java
      index c16d04d6d8..7ee246c357 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java
      @@ -128,6 +128,17 @@ public void updateAllMatching() {
       				}).verifyComplete();
       	}
       
      +	@Test // DATAMONGO-2416
      +	public void updateAllMatchingCriteria() {
      +
      +		template.update(Person.class).matching(where("id").is(han.getId())).apply(new Update().set("firstname", "Han"))
      +				.all().as(StepVerifier::create).consumeNextWith(actual -> {
      +
      +					assertThat(actual.getModifiedCount()).isEqualTo(1L);
      +					assertThat(actual.getUpsertedId()).isNull();
      +				}).verifyComplete();
      +	}
      +
       	@Test // DATAMONGO-1719
       	public void updateWithDifferentDomainClassAndCollection() {
       
      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 216ba31147..769ffb89e1 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
      @@ -100,7 +100,7 @@ void setUp() {
       		doReturn(converter).when(mongoOperationsMock).getConverter();
       		doReturn(executableFind).when(mongoOperationsMock).query(any());
       		doReturn(withQueryMock).when(executableFind).as(any());
      -		doReturn(withQueryMock).when(withQueryMock).matching(any());
      +		doReturn(withQueryMock).when(withQueryMock).matching(any(Query.class));
       
       		when(mongoOperationsMock.remove(any(), any(), anyString())).thenReturn(deleteResultMock);
       	}
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java
      index 38e9a08071..bed41afb3c 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java
      @@ -52,7 +52,10 @@
       import org.springframework.expression.spel.standard.SpelExpressionParser;
       
       /**
      + * Unit tests for {@link AbstractReactiveMongoQuery}.
      + *
        * @author Christoph Strobl
      + * @author Mark Paluch
        * @currentRead Way of Kings - Brandon Sanderson
        */
       @ExtendWith(MockitoExtension.class)
      @@ -81,7 +84,7 @@ void setUp() {
       
       		doReturn(executableFind).when(mongoOperationsMock).query(any());
       		doReturn(withQueryMock).when(executableFind).as(any());
      -		doReturn(withQueryMock).when(withQueryMock).matching(any());
      +		doReturn(withQueryMock).when(withQueryMock).matching(any(Query.class));
       	}
       
       	@Test // DATAMONGO-1854
      
      From a6bd41bcf263731b87059135f0b96c46c1f1a9c5 Mon Sep 17 00:00:00 2001
      From: Mark Paluch 
      Date: Tue, 10 Mar 2020 14:48:46 +0100
      Subject: [PATCH 0111/1381] DATAMONGO-2416 - Polishing.
      
      Reduce visibility of JUnit 5 test classes/methods.
      
      Original Pull Request: #840
      ---
       .../ExecutableFindOperationSupportTests.java  | 122 +++++++++---------
       ...bleMapReduceOperationSupportUnitTests.java |   2 +-
       ...ExecutableRemoveOperationSupportTests.java |  20 +--
       ...ExecutableUpdateOperationSupportTests.java |  48 +++----
       .../ReactiveFindOperationSupportTests.java    | 106 +++++++--------
       .../ReactiveRemoveOperationSupportTests.java  |  26 ++--
       .../ReactiveUpdateOperationSupportTests.java  |  50 +++----
       7 files changed, 187 insertions(+), 187 deletions(-)
      
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
      index 779f59866d..65fae75e61 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
      @@ -55,22 +55,22 @@
        * @author Mark Paluch
        */
       @ExtendWith(MongoTemplateExtension.class)
      -public class ExecutableFindOperationSupportTests {
      +class ExecutableFindOperationSupportTests {
       
       	private static final String STAR_WARS = "star-wars";
       	private static final String STAR_WARS_PLANETS = "star-wars-universe";
       
       	@Template(database = "executable-find-operation-support-tests", initialEntitySet = { Person.class, Planet.class }) //
      -	static MongoTestTemplate template;
      +	private static MongoTestTemplate template;
       
      -	Person han;
      -	Person luke;
      +	private Person han;
      +	private Person luke;
       
      -	Planet alderan;
      -	Planet dantooine;
      +	private Planet alderan;
      +	private Planet dantooine;
       
       	@BeforeEach
      -	public void setUp() {
      +	void setUp() {
       
       		template.flush();
       
      @@ -82,37 +82,37 @@ public void setUp() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void domainTypeIsRequired() {
      +	void domainTypeIsRequired() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.query(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void returnTypeIsRequiredOnSet() {
      +	void returnTypeIsRequiredOnSet() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.query(Person.class).as(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void collectionIsRequiredOnSet() {
      +	void collectionIsRequiredOnSet() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.query(Person.class).inCollection(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAll() {
      +	void findAll() {
       		assertThat(template.query(Person.class).all()).containsExactlyInAnyOrder(han, luke);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllWithCollection() {
      +	void findAllWithCollection() {
       		assertThat(template.query(Human.class).inCollection(STAR_WARS).all()).hasSize(2);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllWithProjection() {
      +	void findAllWithProjection() {
       		assertThat(template.query(Person.class).as(Jedi.class).all()).hasOnlyElementsOfType(Jedi.class).hasSize(2);
       	}
       
       	@Test // DATAMONGO-2041
      -	public void findAllWithProjectionOnEmbeddedType() {
      +	void findAllWithProjectionOnEmbeddedType() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -124,94 +124,94 @@ public void findAllWithProjectionOnEmbeddedType() {
       	}
       
       	@Test // DATAMONGO-1733
      -	public void findByReturningAllValuesAsClosedInterfaceProjection() {
      +	void findByReturningAllValuesAsClosedInterfaceProjection() {
       
       		assertThat(template.query(Person.class).as(PersonProjection.class).all())
       				.hasOnlyElementsOfTypes(PersonProjection.class);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllBy() {
      +	void findAllBy() {
       
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).all())
       				.containsExactlyInAnyOrder(luke);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllByWithCollectionUsingMappingInformation() {
      +	void findAllByWithCollectionUsingMappingInformation() {
       
       		assertThat(template.query(Jedi.class).inCollection(STAR_WARS).matching(query(where("name").is("luke"))).all())
       				.hasSize(1).hasOnlyElementsOfType(Jedi.class);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllByWithCollection() {
      +	void findAllByWithCollection() {
       		assertThat(template.query(Human.class).inCollection(STAR_WARS).matching(query(where("firstname").is("luke"))).all())
       				.hasSize(1);
       	}
       
       	@Test // DATAMONGO-2323
      -	public void findAllAsDocument() {
      +	void findAllAsDocument() {
       		assertThat(
       				template.query(Document.class).inCollection(STAR_WARS).matching(query(where("firstname").is("luke"))).all())
       						.hasSize(1);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllByWithProjection() {
      +	void findAllByWithProjection() {
       
       		assertThat(template.query(Person.class).as(Jedi.class).matching(query(where("firstname").is("luke"))).all())
       				.hasOnlyElementsOfType(Jedi.class).hasSize(1);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findBy() {
      +	void findBy() {
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).one()).contains(luke);
       	}
       
       	@Test // DATAMONGO-2416
      -	public void findByCriteria() {
      +	void findByCriteria() {
       		assertThat(template.query(Person.class).matching(where("firstname").is("luke")).one()).contains(luke);
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findByNoMatch() {
      +	void findByNoMatch() {
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("spock"))).one()).isEmpty();
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findByTooManyResults() {
      +	void findByTooManyResults() {
       		assertThatExceptionOfType(IncorrectResultSizeDataAccessException.class)
       				.isThrownBy(() -> template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).one());
       	}
       
       	@Test // DATAMONGO-1726
      -	public void findByReturningOneValue() {
      +	void findByReturningOneValue() {
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).oneValue()).isEqualTo(luke);
       	}
       
       	@Test // DATAMONGO-1726
      -	public void findByReturningOneValueButTooManyResults() {
      +	void findByReturningOneValueButTooManyResults() {
       		assertThatExceptionOfType(IncorrectResultSizeDataAccessException.class).isThrownBy(
       				() -> template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).oneValue());
       	}
       
       	@Test // DATAMONGO-1726
      -	public void findByReturningFirstValue() {
      +	void findByReturningFirstValue() {
       
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).firstValue())
       				.isEqualTo(luke);
       	}
       
       	@Test // DATAMONGO-1726
      -	public void findByReturningFirstValueForManyResults() {
      +	void findByReturningFirstValueForManyResults() {
       
       		assertThat(template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).firstValue())
       				.isIn(han, luke);
       	}
       
       	@Test // DATAMONGO-1733
      -	public void findByReturningFirstValueAsClosedInterfaceProjection() {
      +	void findByReturningFirstValueAsClosedInterfaceProjection() {
       
       		PersonProjection result = template.query(Person.class).as(PersonProjection.class)
       				.matching(query(where("firstname").is("han"))).firstValue();
      @@ -221,7 +221,7 @@ public void findByReturningFirstValueAsClosedInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1733
      -	public void findByReturningFirstValueAsOpenInterfaceProjection() {
      +	void findByReturningFirstValueAsOpenInterfaceProjection() {
       
       		PersonSpELProjection result = template.query(Person.class).as(PersonSpELProjection.class)
       				.matching(query(where("firstname").is("han"))).firstValue();
      @@ -231,7 +231,7 @@ public void findByReturningFirstValueAsOpenInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void streamAll() {
      +	void streamAll() {
       
       		try (Stream stream = template.query(Person.class).stream()) {
       			assertThat(stream).containsExactlyInAnyOrder(han, luke);
      @@ -239,7 +239,7 @@ public void streamAll() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void streamAllWithCollection() {
      +	void streamAllWithCollection() {
       
       		try (Stream stream = template.query(Human.class).inCollection(STAR_WARS).stream()) {
       			assertThat(stream).hasSize(2);
      @@ -247,7 +247,7 @@ public void streamAllWithCollection() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void streamAllWithProjection() {
      +	void streamAllWithProjection() {
       
       		try (Stream stream = template.query(Person.class).as(Jedi.class).stream()) {
       			assertThat(stream).hasOnlyElementsOfType(Jedi.class).hasSize(2);
      @@ -255,7 +255,7 @@ public void streamAllWithProjection() {
       	}
       
       	@Test // DATAMONGO-1733
      -	public void streamAllReturningResultsAsClosedInterfaceProjection() {
      +	void streamAllReturningResultsAsClosedInterfaceProjection() {
       
       		TerminatingFind operation = template.query(Person.class).as(PersonProjection.class);
       
      @@ -268,7 +268,7 @@ public void streamAllReturningResultsAsClosedInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1733
      -	public void streamAllReturningResultsAsOpenInterfaceProjection() {
      +	void streamAllReturningResultsAsOpenInterfaceProjection() {
       
       		TerminatingFind operation = template.query(Person.class).as(PersonSpELProjection.class);
       
      @@ -281,7 +281,7 @@ public void streamAllReturningResultsAsOpenInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void streamAllBy() {
      +	void streamAllBy() {
       
       		try (Stream stream = template.query(Person.class).matching(query(where("firstname").is("luke"))).stream()) {
       			assertThat(stream).containsExactlyInAnyOrder(luke);
      @@ -289,7 +289,7 @@ public void streamAllBy() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllNearBy() {
      +	void findAllNearBy() {
       
       		GeoResults results = template.query(Planet.class).near(NearQuery.near(-73.9667, 40.78).spherical(true))
       				.all();
      @@ -298,7 +298,7 @@ public void findAllNearBy() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAllNearByWithCollectionAndProjection() {
      +	void findAllNearByWithCollectionAndProjection() {
       
       		GeoResults results = template.query(Object.class).inCollection(STAR_WARS_PLANETS).as(Human.class)
       				.near(NearQuery.near(-73.9667, 40.78).spherical(true)).all();
      @@ -310,7 +310,7 @@ public void findAllNearByWithCollectionAndProjection() {
       	}
       
       	@Test // DATAMONGO-1733
      -	public void findAllNearByReturningGeoResultContentAsClosedInterfaceProjection() {
      +	void findAllNearByReturningGeoResultContentAsClosedInterfaceProjection() {
       
       		GeoResults results = template.query(Planet.class).as(PlanetProjection.class)
       				.near(NearQuery.near(-73.9667, 40.78).spherical(true)).all();
      @@ -323,7 +323,7 @@ public void findAllNearByReturningGeoResultContentAsClosedInterfaceProjection()
       	}
       
       	@Test // DATAMONGO-1733
      -	public void findAllNearByReturningGeoResultContentAsOpenInterfaceProjection() {
      +	void findAllNearByReturningGeoResultContentAsOpenInterfaceProjection() {
       
       		GeoResults results = template.query(Planet.class).as(PlanetSpELProjection.class)
       				.near(NearQuery.near(-73.9667, 40.78).spherical(true)).all();
      @@ -336,29 +336,29 @@ public void findAllNearByReturningGeoResultContentAsOpenInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1728
      -	public void firstShouldReturnFirstEntryInCollection() {
      +	void firstShouldReturnFirstEntryInCollection() {
       		assertThat(template.query(Person.class).first()).isNotEmpty();
       	}
       
       	@Test // DATAMONGO-1734
      -	public void countShouldReturnNrOfElementsInCollectionWhenNoQueryPresent() {
      +	void countShouldReturnNrOfElementsInCollectionWhenNoQueryPresent() {
       		assertThat(template.query(Person.class).count()).isEqualTo(2);
       	}
       
       	@Test // DATAMONGO-1734
      -	public void countShouldReturnNrOfElementsMatchingQuery() {
      +	void countShouldReturnNrOfElementsMatchingQuery() {
       
       		assertThat(template.query(Person.class).matching(query(where("firstname").is(luke.getFirstname()))).count())
       				.isEqualTo(1);
       	}
       
       	@Test // DATAMONGO-1734
      -	public void existsShouldReturnTrueIfAtLeastOneElementExistsInCollection() {
      +	void existsShouldReturnTrueIfAtLeastOneElementExistsInCollection() {
       		assertThat(template.query(Person.class).exists()).isTrue();
       	}
       
       	@Test // DATAMONGO-1734
      -	public void existsShouldReturnFalseIfNoElementExistsInCollection() {
      +	void existsShouldReturnFalseIfNoElementExistsInCollection() {
       
       		template.remove(new BasicQuery("{}"), STAR_WARS);
       
      @@ -366,29 +366,29 @@ public void existsShouldReturnFalseIfNoElementExistsInCollection() {
       	}
       
       	@Test // DATAMONGO-1734
      -	public void existsShouldReturnTrueIfAtLeastOneElementMatchesQuery() {
      +	void existsShouldReturnTrueIfAtLeastOneElementMatchesQuery() {
       
       		assertThat(template.query(Person.class).matching(query(where("firstname").is(luke.getFirstname()))).exists())
       				.isTrue();
       	}
       
       	@Test // DATAMONGO-1734
      -	public void existsShouldReturnFalseWhenNoElementMatchesQuery() {
      +	void existsShouldReturnFalseWhenNoElementMatchesQuery() {
       		assertThat(template.query(Person.class).matching(query(where("firstname").is("spock"))).exists()).isFalse();
       	}
       
       	@Test // DATAMONGO-1734
      -	public void returnsTargetObjectDirectlyIfProjectionInterfaceIsImplemented() {
      +	void returnsTargetObjectDirectlyIfProjectionInterfaceIsImplemented() {
       		assertThat(template.query(Person.class).as(Contact.class).all()).allMatch(it -> it instanceof Person);
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsEmptyListIfNoMatchFound() {
      +	void distinctReturnsEmptyListIfNoMatchFound() {
       		assertThat(template.query(Person.class).distinct("actually-not-property-in-use").as(String.class).all()).isEmpty();
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsSimpleFieldValuesCorrectlyForCollectionHavingReturnTypeSpecifiedThatCanBeConvertedDirectlyByACodec() {
      +	void distinctReturnsSimpleFieldValuesCorrectlyForCollectionHavingReturnTypeSpecifiedThatCanBeConvertedDirectlyByACodec() {
       
       		Person anakin = new Person();
       		anakin.firstname = "anakin";
      @@ -401,7 +401,7 @@ public void distinctReturnsSimpleFieldValuesCorrectlyForCollectionHavingReturnTy
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsSimpleFieldValuesCorrectly() {
      +	void distinctReturnsSimpleFieldValuesCorrectly() {
       
       		Person anakin = new Person();
       		anakin.firstname = "anakin";
      @@ -424,7 +424,7 @@ public void distinctReturnsSimpleFieldValuesCorrectly() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsComplexValuesCorrectly() {
      +	void distinctReturnsComplexValuesCorrectly() {
       
       		Sith sith = new Sith();
       		sith.rank = "lord";
      @@ -439,7 +439,7 @@ public void distinctReturnsComplexValuesCorrectly() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsComplexValuesCorrectlyHavingReturnTypeSpecified() {
      +	void distinctReturnsComplexValuesCorrectlyHavingReturnTypeSpecified() {
       
       		Sith sith = new Sith();
       		sith.rank = "lord";
      @@ -455,7 +455,7 @@ public void distinctReturnsComplexValuesCorrectlyHavingReturnTypeSpecified() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsComplexValuesCorrectlyHavingReturnTypeDocumentSpecified() {
      +	void distinctReturnsComplexValuesCorrectlyHavingReturnTypeDocumentSpecified() {
       
       		Sith sith = new Sith();
       		sith.rank = "lord";
      @@ -471,21 +471,21 @@ public void distinctReturnsComplexValuesCorrectlyHavingReturnTypeDocumentSpecifi
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctMapsFieldNameCorrectly() {
      +	void distinctMapsFieldNameCorrectly() {
       
       		assertThat(template.query(Jedi.class).inCollection(STAR_WARS).distinct("name").as(String.class).all())
       				.containsExactlyInAnyOrder("han", "luke");
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsRawValuesIfReturnTypeIsBsonValue() {
      +	void distinctReturnsRawValuesIfReturnTypeIsBsonValue() {
       
       		assertThat(template.query(Person.class).distinct("lastname").as(BsonValue.class).all())
       				.containsExactlyInAnyOrder(new BsonString("solo"), new BsonString("skywalker"));
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsValuesMappedToTheirJavaTypeEvenWhenNotExplicitlyDefinedByTheDomainType() {
      +	void distinctReturnsValuesMappedToTheirJavaTypeEvenWhenNotExplicitlyDefinedByTheDomainType() {
       
       		template.save(new Document("darth", "vader"), STAR_WARS);
       
      @@ -493,7 +493,7 @@ public void distinctReturnsValuesMappedToTheirJavaTypeEvenWhenNotExplicitlyDefin
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsMappedDomainTypeForProjections() {
      +	void distinctReturnsMappedDomainTypeForProjections() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -505,7 +505,7 @@ public void distinctReturnsMappedDomainTypeForProjections() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctAlllowsQueryUsingObjectSourceType() {
      +	void distinctAlllowsQueryUsingObjectSourceType() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -517,7 +517,7 @@ public void distinctAlllowsQueryUsingObjectSourceType() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsMappedDomainTypeExtractedFromPropertyWhenNoExplicitTypePresent() {
      +	void distinctReturnsMappedDomainTypeExtractedFromPropertyWhenNoExplicitTypePresent() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -531,7 +531,7 @@ public void distinctReturnsMappedDomainTypeExtractedFromPropertyWhenNoExplicitTy
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctThrowsExceptionWhenExplicitMappingTypeCannotBeApplied() {
      +	void distinctThrowsExceptionWhenExplicitMappingTypeCannotBeApplied() {
       		assertThatExceptionOfType(InvalidDataAccessApiUsageException.class)
       				.isThrownBy(() -> template.query(Person.class).distinct("firstname").as(Long.class).all());
       	}
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java
      index bca48a3465..c6b551cdc6 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupportUnitTests.java
      @@ -44,7 +44,7 @@
        * @currentRead Beyond the Shadows - Brent Weeks
        */
       @ExtendWith(MockitoExtension.class)
      -public class ExecutableMapReduceOperationSupportUnitTests {
      +class ExecutableMapReduceOperationSupportUnitTests {
       
       	private static final String STAR_WARS = "star-wars";
       	private static final String MAP_FUNCTION = "function() { emit(this.id, this.firstname) }";
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java
      index 52ce526e9a..8bca074665 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java
      @@ -41,18 +41,18 @@
        * @author Mark Paluch
        */
       @ExtendWith(MongoTemplateExtension.class)
      -public class ExecutableRemoveOperationSupportTests {
      +class ExecutableRemoveOperationSupportTests {
       
       	private static final String STAR_WARS = "star-wars";
       
       	@Template(initialEntitySet = Person.class) //
      -	static MongoTestTemplate template;
      +	private static MongoTestTemplate template;
       
      -	Person han;
      -	Person luke;
      +	private Person han;
      +	private Person luke;
       
       	@BeforeEach
      -	public void setUp() {
      +	void setUp() {
       
       		template.flush();
       
      @@ -69,7 +69,7 @@ public void setUp() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void removeAll() {
      +	void removeAll() {
       
       		DeleteResult result = template.remove(Person.class).all();
       
      @@ -77,7 +77,7 @@ public void removeAll() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void removeAllMatching() {
      +	void removeAllMatching() {
       
       		DeleteResult result = template.remove(Person.class).matching(query(where("firstname").is("han"))).all();
       
      @@ -85,7 +85,7 @@ public void removeAllMatching() {
       	}
       
       	@Test // DATAMONGO-2416
      -	public void removeAllMatchingCriteria() {
      +	void removeAllMatchingCriteria() {
       
       		DeleteResult result = template.remove(Person.class).matching(where("firstname").is("han")).all();
       
      @@ -93,7 +93,7 @@ public void removeAllMatchingCriteria() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
      +	void removeAllMatchingWithAlternateDomainTypeAndCollection() {
       
       		DeleteResult result = template.remove(Jedi.class).inCollection(STAR_WARS).matching(query(where("name").is("luke")))
       				.all();
      @@ -102,7 +102,7 @@ public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void removeAndReturnAllMatching() {
      +	void removeAndReturnAllMatching() {
       
       		List result = template.remove(Person.class).matching(query(where("firstname").is("han"))).findAndRemove();
       
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java
      index 2c5196003d..3334848460 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java
      @@ -44,18 +44,18 @@
        * @author Mark Paluch
        */
       @ExtendWith(MongoTemplateExtension.class)
      -public class ExecutableUpdateOperationSupportTests {
      +class ExecutableUpdateOperationSupportTests {
       
       	private static final String STAR_WARS = "star-wars";
       
       	@Template(initialEntitySet = { Human.class, Jedi.class, Person.class }) //
      -	static MongoTestTemplate template;
      +	private static MongoTestTemplate template;
       
      -	Person han;
      -	Person luke;
      +	private Person han;
      +	private Person luke;
       
       	@BeforeEach
      -	public void setUp() {
      +	void setUp() {
       
       		template.flush();
       
      @@ -72,28 +72,28 @@ public void setUp() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void domainTypeIsRequired() {
      +	void domainTypeIsRequired() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.update(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void updateIsRequired() {
      +	void updateIsRequired() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.update(Person.class).apply(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void collectionIsRequiredOnSet() {
      +	void collectionIsRequiredOnSet() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.update(Person.class).inCollection(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAndModifyOptionsAreRequiredOnSet() {
      +	void findAndModifyOptionsAreRequiredOnSet() {
       		assertThatIllegalArgumentException()
       				.isThrownBy(() -> template.update(Person.class).apply(new Update()).withOptions(null));
       	}
       
       	@Test // DATAMONGO-1563
      -	public void updateFirst() {
      +	void updateFirst() {
       
       		UpdateResult result = template.update(Person.class).apply(new Update().set("firstname", "Han")).first();
       
      @@ -102,7 +102,7 @@ public void updateFirst() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void updateAll() {
      +	void updateAll() {
       
       		UpdateResult result = template.update(Person.class).apply(new Update().set("firstname", "Han")).all();
       
      @@ -111,7 +111,7 @@ public void updateAll() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void updateAllMatching() {
      +	void updateAllMatching() {
       
       		UpdateResult result = template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han"))
       				.all();
      @@ -121,7 +121,7 @@ public void updateAllMatching() {
       	}
       
       	@Test // DATAMONGO-2416
      -	public void updateAllMatchingCriteria() {
      +	void updateAllMatchingCriteria() {
       
       		UpdateResult result = template.update(Person.class).matching(where("id").is(han.getId()))
       				.apply(new Update().set("firstname", "Han"))
      @@ -132,7 +132,7 @@ public void updateAllMatchingCriteria() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void updateWithDifferentDomainClassAndCollection() {
      +	void updateWithDifferentDomainClassAndCollection() {
       
       		UpdateResult result = template.update(Jedi.class).inCollection(STAR_WARS)
       				.matching(query(where("_id").is(han.getId()))).apply(new Update().set("name", "Han")).all();
      @@ -144,7 +144,7 @@ public void updateWithDifferentDomainClassAndCollection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAndModifyValue() {
      +	void findAndModifyValue() {
       
       		Person result = template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han"))
       				.findAndModifyValue();
      @@ -155,7 +155,7 @@ public void findAndModifyValue() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAndModify() {
      +	void findAndModify() {
       
       		Optional result = template.update(Person.class).matching(queryHan())
       				.apply(new Update().set("firstname", "Han")).findAndModify();
      @@ -166,7 +166,7 @@ public void findAndModify() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAndModifyWithDifferentDomainTypeAndCollection() {
      +	void findAndModifyWithDifferentDomainTypeAndCollection() {
       
       		Optional result = template.update(Jedi.class).inCollection(STAR_WARS)
       				.matching(query(where("_id").is(han.getId()))).apply(new Update().set("name", "Han")).findAndModify();
      @@ -177,7 +177,7 @@ public void findAndModifyWithDifferentDomainTypeAndCollection() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void findAndModifyWithOptions() {
      +	void findAndModifyWithOptions() {
       
       		Optional result = template.update(Person.class).matching(queryHan())
       				.apply(new Update().set("firstname", "Han")).withOptions(FindAndModifyOptions.options().returnNew(true))
      @@ -187,7 +187,7 @@ public void findAndModifyWithOptions() {
       	}
       
       	@Test // DATAMONGO-1563
      -	public void upsert() {
      +	void upsert() {
       
       		UpdateResult result = template.update(Person.class).matching(query(where("id").is("id-3")))
       				.apply(new Update().set("firstname", "Chewbacca")).upsert();
      @@ -197,7 +197,7 @@ public void upsert() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceValue() {
      +	void findAndReplaceValue() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -210,7 +210,7 @@ public void findAndReplaceValue() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplace() {
      +	void findAndReplace() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -223,7 +223,7 @@ public void findAndReplace() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceWithCollection() {
      +	void findAndReplaceWithCollection() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -237,7 +237,7 @@ public void findAndReplaceWithCollection() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceWithOptions() {
      +	void findAndReplaceWithOptions() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -249,7 +249,7 @@ public void findAndReplaceWithOptions() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceWithProjection() {
      +	void findAndReplaceWithProjection() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java
      index 70a0975a5c..e2e200c96a 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java
      @@ -61,20 +61,20 @@
        * @author Christoph Strobl
        */
       @ExtendWith(MongoClientExtension.class)
      -public class ReactiveFindOperationSupportTests {
      +class ReactiveFindOperationSupportTests {
       
       	private static final String STAR_WARS = "star-wars";
      -	MongoTemplate blocking;
      -	ReactiveMongoTemplate template;
      +	private MongoTemplate blocking;
      +	private ReactiveMongoTemplate template;
       
      -	static @Client MongoClient client;
      -	static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient;
      +	private static @Client MongoClient client;
      +	private static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient;
       
      -	Person han;
      -	Person luke;
      +	private Person han;
      +	private Person luke;
       
       	@BeforeEach
      -	public void setUp() {
      +	void setUp() {
       
       		blocking = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, "ExecutableFindOperationSupportTests"));
       		recreateCollection(STAR_WARS, false);
      @@ -113,22 +113,22 @@ void recreateCollection(String collectionName, boolean capped) {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void domainTypeIsRequired() {
      +	void domainTypeIsRequired() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.query(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void returnTypeIsRequiredOnSet() {
      +	void returnTypeIsRequiredOnSet() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.query(Person.class).as(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void collectionIsRequiredOnSet() {
      +	void collectionIsRequiredOnSet() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.query(Person.class).inCollection(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAll() {
      +	void findAll() {
       
       		template.query(Person.class).all().collectList().as(StepVerifier::create).consumeNextWith(actual -> {
       			assertThat(actual).containsExactlyInAnyOrder(han, luke);
      @@ -136,19 +136,19 @@ public void findAll() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllWithCollection() {
      +	void findAllWithCollection() {
       		template.query(Human.class).inCollection(STAR_WARS).all().as(StepVerifier::create).expectNextCount(2)
       				.verifyComplete();
       	}
       
       	@Test // DATAMONGO-2323
      -	public void findAllAsDocumentDocument() {
      +	void findAllAsDocumentDocument() {
       		template.query(Document.class).inCollection(STAR_WARS).all().as(StepVerifier::create).expectNextCount(2)
       				.verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllWithProjection() {
      +	void findAllWithProjection() {
       
       		template.query(Person.class).as(Jedi.class).all().map(it -> it.getClass().getName()).as(StepVerifier::create) //
       				.expectNext(Jedi.class.getName(), Jedi.class.getName()) //
      @@ -156,7 +156,7 @@ public void findAllWithProjection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllBy() {
      +	void findAllBy() {
       
       		template.query(Person.class).matching(query(where("firstname").is("luke"))).all().as(StepVerifier::create) //
       				.expectNext(luke) //
      @@ -164,7 +164,7 @@ public void findAllBy() {
       	}
       
       	@Test // DATAMONGO-2416
      -	public void findAllByCriteria() {
      +	void findAllByCriteria() {
       
       		template.query(Person.class).matching(where("firstname").is("luke")).all().as(StepVerifier::create) //
       				.expectNext(luke) //
      @@ -172,7 +172,7 @@ public void findAllByCriteria() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllByWithCollectionUsingMappingInformation() {
      +	void findAllByWithCollectionUsingMappingInformation() {
       
       		template.query(Jedi.class).inCollection(STAR_WARS).matching(query(where("name").is("luke"))).all()
       				.as(StepVerifier::create).consumeNextWith(it -> assertThat(it).isInstanceOf(Jedi.class)) //
      @@ -180,7 +180,7 @@ public void findAllByWithCollectionUsingMappingInformation() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllByWithCollection() {
      +	void findAllByWithCollection() {
       
       		template.query(Human.class).inCollection(STAR_WARS).matching(query(where("firstname").is("luke"))).all()
       				.as(StepVerifier::create).expectNextCount(1) //
      @@ -188,7 +188,7 @@ public void findAllByWithCollection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllByWithProjection() {
      +	void findAllByWithProjection() {
       
       		template.query(Person.class).as(Jedi.class).matching(query(where("firstname").is("luke"))).all()
       				.as(StepVerifier::create).consumeNextWith(it -> assertThat(it).isInstanceOf(Jedi.class)) //
      @@ -196,7 +196,7 @@ public void findAllByWithProjection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllByWithClosedInterfaceProjection() {
      +	void findAllByWithClosedInterfaceProjection() {
       
       		template.query(Person.class).as(PersonProjection.class).matching(query(where("firstname").is("luke"))).all()
       				.as(StepVerifier::create).consumeNextWith(it -> {
      @@ -208,7 +208,7 @@ public void findAllByWithClosedInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllByWithOpenInterfaceProjection() {
      +	void findAllByWithOpenInterfaceProjection() {
       
       		template.query(Person.class).as(PersonSpELProjection.class).matching(query(where("firstname").is("luke"))).all()
       				.as(StepVerifier::create).consumeNextWith(it -> {
      @@ -220,7 +220,7 @@ public void findAllByWithOpenInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findBy() {
      +	void findBy() {
       
       		template.query(Person.class).matching(query(where("firstname").is("luke"))).one().as(StepVerifier::create)
       				.expectNext(luke) //
      @@ -228,14 +228,14 @@ public void findBy() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findByNoMatch() {
      +	void findByNoMatch() {
       
       		template.query(Person.class).matching(query(where("firstname").is("spock"))).one().as(StepVerifier::create)
       				.verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findByTooManyResults() {
      +	void findByTooManyResults() {
       
       		template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).one().as(StepVerifier::create)
       				.expectError(IncorrectResultSizeDataAccessException.class) //
      @@ -243,7 +243,7 @@ public void findByTooManyResults() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllNearBy() {
      +	void findAllNearBy() {
       
       		blocking.indexOps(Planet.class).ensureIndex(
       				new GeospatialIndex("coordinates").typed(GeoSpatialIndexType.GEO_2DSPHERE).named("planet-coordinate-idx"));
      @@ -263,7 +263,7 @@ public void findAllNearBy() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllNearByWithCollectionAndProjection() {
      +	void findAllNearByWithCollectionAndProjection() {
       
       		blocking.indexOps(Planet.class).ensureIndex(
       				new GeospatialIndex("coordinates").typed(GeoSpatialIndexType.GEO_2DSPHERE).named("planet-coordinate-idx"));
      @@ -286,7 +286,7 @@ public void findAllNearByWithCollectionAndProjection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllNearByReturningGeoResultContentAsClosedInterfaceProjection() {
      +	void findAllNearByReturningGeoResultContentAsClosedInterfaceProjection() {
       
       		blocking.indexOps(Planet.class).ensureIndex(
       				new GeospatialIndex("coordinates").typed(GeoSpatialIndexType.GEO_2DSPHERE).named("planet-coordinate-idx"));
      @@ -309,7 +309,7 @@ public void findAllNearByReturningGeoResultContentAsClosedInterfaceProjection()
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAllNearByReturningGeoResultContentAsOpenInterfaceProjection() {
      +	void findAllNearByReturningGeoResultContentAsOpenInterfaceProjection() {
       
       		blocking.indexOps(Planet.class).ensureIndex(
       				new GeospatialIndex("coordinates").typed(GeoSpatialIndexType.GEO_2DSPHERE).named("planet-coordinate-idx"));
      @@ -332,7 +332,7 @@ public void findAllNearByReturningGeoResultContentAsOpenInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-2080
      -	public void tail() throws InterruptedException {
      +	void tail() throws InterruptedException {
       
       		recreateCollection(STAR_WARS, true);
       		insertObjects();
      @@ -360,7 +360,7 @@ public void tail() throws InterruptedException {
       	}
       
       	@Test // DATAMONGO-2080
      -	public void tailWithProjection() {
      +	void tailWithProjection() {
       
       		recreateCollection(STAR_WARS, true);
       		insertObjects();
      @@ -373,7 +373,7 @@ public void tailWithProjection() {
       	}
       
       	@Test // DATAMONGO-2080
      -	public void tailWithClosedInterfaceProjection() {
      +	void tailWithClosedInterfaceProjection() {
       
       		recreateCollection(STAR_WARS, true);
       		insertObjects();
      @@ -390,7 +390,7 @@ public void tailWithClosedInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-2080
      -	public void tailWithOpenInterfaceProjection() {
      +	void tailWithOpenInterfaceProjection() {
       
       		recreateCollection(STAR_WARS, true);
       		insertObjects();
      @@ -407,17 +407,17 @@ public void tailWithOpenInterfaceProjection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void firstShouldReturnFirstEntryInCollection() {
      +	void firstShouldReturnFirstEntryInCollection() {
       		template.query(Person.class).first().as(StepVerifier::create).expectNextCount(1).verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void countShouldReturnNrOfElementsInCollectionWhenNoQueryPresent() {
      +	void countShouldReturnNrOfElementsInCollectionWhenNoQueryPresent() {
       		template.query(Person.class).count().as(StepVerifier::create).expectNext(2L).verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void countShouldReturnNrOfElementsMatchingQuery() {
      +	void countShouldReturnNrOfElementsMatchingQuery() {
       
       		template.query(Person.class).matching(query(where("firstname").is(luke.getFirstname()))).count()
       				.as(StepVerifier::create).expectNext(1L) //
      @@ -425,12 +425,12 @@ public void countShouldReturnNrOfElementsMatchingQuery() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void existsShouldReturnTrueIfAtLeastOneElementExistsInCollection() {
      +	void existsShouldReturnTrueIfAtLeastOneElementExistsInCollection() {
       		template.query(Person.class).exists().as(StepVerifier::create).expectNext(true).verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void existsShouldReturnFalseIfNoElementExistsInCollection() {
      +	void existsShouldReturnFalseIfNoElementExistsInCollection() {
       
       		blocking.remove(new BasicQuery("{}"), STAR_WARS);
       
      @@ -438,7 +438,7 @@ public void existsShouldReturnFalseIfNoElementExistsInCollection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void existsShouldReturnTrueIfAtLeastOneElementMatchesQuery() {
      +	void existsShouldReturnTrueIfAtLeastOneElementMatchesQuery() {
       
       		template.query(Person.class).matching(query(where("firstname").is(luke.getFirstname()))).exists()
       				.as(StepVerifier::create).expectNext(true) //
      @@ -446,7 +446,7 @@ public void existsShouldReturnTrueIfAtLeastOneElementMatchesQuery() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void existsShouldReturnFalseWhenNoElementMatchesQuery() {
      +	void existsShouldReturnFalseWhenNoElementMatchesQuery() {
       
       		template.query(Person.class).matching(query(where("firstname").is("spock"))).exists().as(StepVerifier::create)
       				.expectNext(false) //
      @@ -454,14 +454,14 @@ public void existsShouldReturnFalseWhenNoElementMatchesQuery() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsEmptyListIfNoMatchFound() {
      +	void distinctReturnsEmptyListIfNoMatchFound() {
       
       		template.query(Person.class).distinct("actually-not-property-in-use").as(String.class).all()
       				.as(StepVerifier::create).verifyComplete();
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsSimpleFieldValuesCorrectlyForCollectionHavingReturnTypeSpecifiedThatCanBeConvertedDirectlyByACodec() {
      +	void distinctReturnsSimpleFieldValuesCorrectlyForCollectionHavingReturnTypeSpecifiedThatCanBeConvertedDirectlyByACodec() {
       
       		Person anakin = new Person();
       		anakin.firstname = "anakin";
      @@ -475,7 +475,7 @@ public void distinctReturnsSimpleFieldValuesCorrectlyForCollectionHavingReturnTy
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsSimpleFieldValuesCorrectly() {
      +	void distinctReturnsSimpleFieldValuesCorrectly() {
       
       		Person anakin = new Person();
       		anakin.firstname = "anakin";
      @@ -503,7 +503,7 @@ public void distinctReturnsSimpleFieldValuesCorrectly() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsComplexValuesCorrectly() {
      +	void distinctReturnsComplexValuesCorrectly() {
       
       		Sith sith = new Sith();
       		sith.rank = "lord";
      @@ -520,7 +520,7 @@ public void distinctReturnsComplexValuesCorrectly() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsComplexValuesCorrectlyHavingReturnTypeSpecified() {
      +	void distinctReturnsComplexValuesCorrectlyHavingReturnTypeSpecified() {
       
       		Sith sith = new Sith();
       		sith.rank = "lord";
      @@ -537,7 +537,7 @@ public void distinctReturnsComplexValuesCorrectlyHavingReturnTypeSpecified() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsComplexValuesCorrectlyReturnTypeDocumentSpecified() {
      +	void distinctReturnsComplexValuesCorrectlyReturnTypeDocumentSpecified() {
       
       		Sith sith = new Sith();
       		sith.rank = "lord";
      @@ -554,7 +554,7 @@ public void distinctReturnsComplexValuesCorrectlyReturnTypeDocumentSpecified() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctMapsFieldNameCorrectly() {
      +	void distinctMapsFieldNameCorrectly() {
       
       		template.query(Jedi.class).inCollection(STAR_WARS).distinct("name").as(String.class).all().as(StepVerifier::create)
       				.assertNext(in("han", "luke")).assertNext(in("han", "luke")) //
      @@ -562,7 +562,7 @@ public void distinctMapsFieldNameCorrectly() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsRawValuesIfReturnTypeIsBsonValue() {
      +	void distinctReturnsRawValuesIfReturnTypeIsBsonValue() {
       
       		Consumer inValues = in(new BsonString("solo"), new BsonString("skywalker"));
       		template.query(Person.class).distinct("lastname").as(BsonValue.class).all().as(StepVerifier::create)
      @@ -572,7 +572,7 @@ public void distinctReturnsRawValuesIfReturnTypeIsBsonValue() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsValuesMappedToTheirJavaTypeEvenWhenNotExplicitlyDefinedByTheDomainType() {
      +	void distinctReturnsValuesMappedToTheirJavaTypeEvenWhenNotExplicitlyDefinedByTheDomainType() {
       
       		blocking.save(new Document("darth", "vader"), STAR_WARS);
       
      @@ -582,7 +582,7 @@ public void distinctReturnsValuesMappedToTheirJavaTypeEvenWhenNotExplicitlyDefin
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsMappedDomainTypeForProjections() {
      +	void distinctReturnsMappedDomainTypeForProjections() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -595,7 +595,7 @@ public void distinctReturnsMappedDomainTypeForProjections() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctAlllowsQueryUsingObjectSourceType() {
      +	void distinctAlllowsQueryUsingObjectSourceType() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -608,7 +608,7 @@ public void distinctAlllowsQueryUsingObjectSourceType() {
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctReturnsMappedDomainTypeExtractedFromPropertyWhenNoExplicitTypePresent() {
      +	void distinctReturnsMappedDomainTypeExtractedFromPropertyWhenNoExplicitTypePresent() {
       
       		luke.father = new Person();
       		luke.father.firstname = "anakin";
      @@ -624,7 +624,7 @@ public void distinctReturnsMappedDomainTypeExtractedFromPropertyWhenNoExplicitTy
       	}
       
       	@Test // DATAMONGO-1761
      -	public void distinctThrowsExceptionWhenExplicitMappingTypeCannotBeApplied() {
      +	void distinctThrowsExceptionWhenExplicitMappingTypeCannotBeApplied() {
       
       		template.query(Person.class).distinct("firstname").as(Long.class).all().as(StepVerifier::create)
       				.expectError(InvalidDataAccessApiUsageException.class) //
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java
      index efd8d5a7fb..0363205390 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupportTests.java
      @@ -38,20 +38,20 @@
        * @author Mark Paluch
        */
       @ExtendWith(MongoClientExtension.class)
      -public class ReactiveRemoveOperationSupportTests {
      +class ReactiveRemoveOperationSupportTests {
       
       	private static final String STAR_WARS = "star-wars";
      -	static @Client MongoClient client;
      -	static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient;
      +	private static @Client MongoClient client;
      +	private static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient;
       
      -	MongoTemplate blocking;
      -	ReactiveMongoTemplate template;
      +	private MongoTemplate blocking;
      +	private ReactiveMongoTemplate template;
       
      -	Person han;
      -	Person luke;
      +	private Person han;
      +	private Person luke;
       
       	@BeforeEach
      -	public void setUp() {
      +	void setUp() {
       
       		blocking = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, "ExecutableRemoveOperationSupportTests"));
       		blocking.dropCollection(STAR_WARS);
      @@ -71,7 +71,7 @@ public void setUp() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void removeAll() {
      +	void removeAll() {
       
       		template.remove(Person.class).all().as(StepVerifier::create).consumeNextWith(actual -> {
       			assertThat(actual.getDeletedCount()).isEqualTo(2L);
      @@ -79,21 +79,21 @@ public void removeAll() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void removeAllMatching() {
      +	void removeAllMatching() {
       
       		template.remove(Person.class).matching(query(where("firstname").is("han"))).all().as(StepVerifier::create)
       				.consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L)).verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void removeAllMatchingCriteria() {
      +	void removeAllMatchingCriteria() {
       
       		template.remove(Person.class).matching(where("firstname").is("han")).all().as(StepVerifier::create)
       				.consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L)).verifyComplete();
       	}
       
       	@Test // DATAMONGO-1719
      -	public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
      +	void removeAllMatchingWithAlternateDomainTypeAndCollection() {
       
       		template.remove(Jedi.class).inCollection(STAR_WARS).matching(query(where("name").is("luke"))).all()
       				.as(StepVerifier::create).consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L))
      @@ -101,7 +101,7 @@ public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void removeAndReturnAllMatching() {
      +	void removeAndReturnAllMatching() {
       
       		template.remove(Person.class).matching(query(where("firstname").is("han"))).findAndRemove().as(StepVerifier::create)
       				.expectNext(han).verifyComplete();
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java
      index 7ee246c357..1a0fd0ddf0 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java
      @@ -41,20 +41,20 @@
        * @author Mark Paluch
        */
       @ExtendWith(MongoClientExtension.class)
      -public class ReactiveUpdateOperationSupportTests {
      +class ReactiveUpdateOperationSupportTests {
       
       	private static final String STAR_WARS = "star-wars";
      -	static @Client MongoClient client;
      -	static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient;
      +	private static @Client MongoClient client;
      +	private static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient;
       
      -	MongoTemplate blocking;
      -	ReactiveMongoTemplate template;
      +	private MongoTemplate blocking;
      +	private ReactiveMongoTemplate template;
       
      -	Person han;
      -	Person luke;
      +	private Person han;
      +	private Person luke;
       
       	@BeforeEach
      -	public void setUp() {
      +	void setUp() {
       
       		blocking = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, "ExecutableUpdateOperationSupportTests"));
       		blocking.dropCollection(STAR_WARS);
      @@ -74,28 +74,28 @@ public void setUp() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void domainTypeIsRequired() {
      +	void domainTypeIsRequired() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.update(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void updateIsRequired() {
      +	void updateIsRequired() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.update(Person.class).apply(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void collectionIsRequiredOnSet() {
      +	void collectionIsRequiredOnSet() {
       		assertThatIllegalArgumentException().isThrownBy(() -> template.update(Person.class).inCollection(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAndModifyOptionsAreRequiredOnSet() {
      +	void findAndModifyOptionsAreRequiredOnSet() {
       		assertThatIllegalArgumentException()
       				.isThrownBy(() -> template.update(Person.class).apply(new Update()).withOptions(null));
       	}
       
       	@Test // DATAMONGO-1719
      -	public void updateFirst() {
      +	void updateFirst() {
       
       		template.update(Person.class).apply(new Update().set("firstname", "Han")).first().as(StepVerifier::create)
       				.consumeNextWith(actual -> {
      @@ -107,7 +107,7 @@ public void updateFirst() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void updateAll() {
      +	void updateAll() {
       
       		template.update(Person.class).apply(new Update().set("firstname", "Han")).all().as(StepVerifier::create)
       				.consumeNextWith(actual -> {
      @@ -118,7 +118,7 @@ public void updateAll() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void updateAllMatching() {
      +	void updateAllMatching() {
       
       		template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han")).all()
       				.as(StepVerifier::create).consumeNextWith(actual -> {
      @@ -129,7 +129,7 @@ public void updateAllMatching() {
       	}
       
       	@Test // DATAMONGO-2416
      -	public void updateAllMatchingCriteria() {
      +	void updateAllMatchingCriteria() {
       
       		template.update(Person.class).matching(where("id").is(han.getId())).apply(new Update().set("firstname", "Han"))
       				.all().as(StepVerifier::create).consumeNextWith(actual -> {
      @@ -140,7 +140,7 @@ public void updateAllMatchingCriteria() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void updateWithDifferentDomainClassAndCollection() {
      +	void updateWithDifferentDomainClassAndCollection() {
       
       		template.update(Jedi.class).inCollection(STAR_WARS).matching(query(where("_id").is(han.getId())))
       				.apply(new Update().set("name", "Han")).all().as(StepVerifier::create).consumeNextWith(actual -> {
      @@ -154,7 +154,7 @@ public void updateWithDifferentDomainClassAndCollection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAndModify() {
      +	void findAndModify() {
       
       		template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han")).findAndModify()
       				.as(StepVerifier::create).expectNext(han).verifyComplete();
      @@ -164,7 +164,7 @@ public void findAndModify() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAndModifyWithDifferentDomainTypeAndCollection() {
      +	void findAndModifyWithDifferentDomainTypeAndCollection() {
       
       		template.update(Jedi.class).inCollection(STAR_WARS).matching(query(where("_id").is(han.getId())))
       				.apply(new Update().set("name", "Han")).findAndModify().as(StepVerifier::create)
      @@ -175,7 +175,7 @@ public void findAndModifyWithDifferentDomainTypeAndCollection() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void findAndModifyWithOptions() {
      +	void findAndModifyWithOptions() {
       
       		template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han"))
       				.withOptions(FindAndModifyOptions.options().returnNew(true)).findAndModify().as(StepVerifier::create)
      @@ -186,7 +186,7 @@ public void findAndModifyWithOptions() {
       	}
       
       	@Test // DATAMONGO-1719
      -	public void upsert() {
      +	void upsert() {
       
       		template.update(Person.class).matching(query(where("id").is("id-3")))
       				.apply(new Update().set("firstname", "Chewbacca")).upsert().as(StepVerifier::create).consumeNextWith(actual -> {
      @@ -197,7 +197,7 @@ public void upsert() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplace() {
      +	void findAndReplace() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -213,7 +213,7 @@ public void findAndReplace() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceWithProjection() {
      +	void findAndReplaceWithProjection() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -225,7 +225,7 @@ public void findAndReplaceWithProjection() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceWithCollection() {
      +	void findAndReplaceWithCollection() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      @@ -241,7 +241,7 @@ public void findAndReplaceWithCollection() {
       	}
       
       	@Test // DATAMONGO-1827
      -	public void findAndReplaceWithOptions() {
      +	void findAndReplaceWithOptions() {
       
       		Person luke = new Person();
       		luke.firstname = "Luke";
      
      From a04821ff90f5a5e4f96294341b3061f5d802db12 Mon Sep 17 00:00:00 2001
      From: Mark Paluch 
      Date: Thu, 19 Mar 2020 15:37:30 +0100
      Subject: [PATCH 0112/1381] DATAMONGO-2497 - Update documentation regarding
       @Transient properties usage in the persistence constructor.
      
      ---
       src/main/asciidoc/reference/mapping.adoc | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc
      index 48eee558da..d0bcf96dc7 100644
      --- a/src/main/asciidoc/reference/mapping.adoc
      +++ b/src/main/asciidoc/reference/mapping.adoc
      @@ -427,7 +427,7 @@ The MappingMongoConverter can use metadata to drive the mapping of objects to do
       * `@TextIndexed`: Applied at the field level to mark the field to be included in the text index.
       * `@HashIndexed`: Applied at the field level for usage within a hashed index to partition data across a sharded cluster.
       * `@Language`: Applied at the field level to set the language override property for text index.
      -* `@Transient`: By default all private fields are mapped to the document, this annotation excludes the field where it is applied from being stored in the database
      +* `@Transient`: By default, all fields are mapped to the document. This annotation excludes the field where it is applied from being stored in the database. Transient properties cannot be used within a persistence constructor as the converter cannot materialize a value for the constructor argument.
       * `@PersistenceConstructor`: Marks a given constructor - even a package protected one - to use when instantiating the object from the database. Constructor arguments are mapped by name to the key values in the retrieved Document.
       * `@Value`: This annotation is part of the Spring Framework . Within the mapping framework it can be applied to constructor arguments. This lets you use a Spring Expression Language statement to transform a key's value retrieved in the database before it is used to construct a domain object. In order to reference a property of a given document one has to use expressions like: `@Value("#root.myProperty")` where `root` refers to the root of the given document.
       * `@Field`: Applied at the field level it allows to describe the name and type of the field as it will be represented in the MongoDB BSON document thus allowing the name and type to be different than the fieldname of the class as well as the property type.
      
      From 7b5fea960f35d3a865fc233ecf6d0a6e45988db6 Mon Sep 17 00:00:00 2001
      From: =?UTF-8?q?Enrique=20Le=C3=B3n=20Molina?= 
      Date: Sat, 15 Feb 2020 21:10:47 +0100
      Subject: [PATCH 0113/1381] DATAMONGO-2475 - MongodbDocumentSerializer: reduce
       nested ANDs and ORs.
      
      Reduce the number of nested $and / $or clauses by combining them into a single document where possible. This allows to simplify the following statement
      
      {
        "$or": [
          {
            "$or": [
              {
                "$or": [
                  {
                    "$or": [
                      { "firstname": "Hencxjo" },
                      { "lastname": "Leon" }
                    ]
                  },
                  { "age": { "$lte": 30 } }
                ]
              },
              { "age": { "$gte": 20 } }
            ]
          },
          { "uniqueId": { "$exists": false } }
        ]
      }
      
      to just
      
      {
       "$or": [
         { "firstname": "Hencxjo" },
         { "lastname": "Leon" },
         { "age": { "$lte": 30 } },
         { "age": { "$gte": 20 } },
         { "uniqueId": { "$exists": false } }
       ]
      }
      
      Original Pull Request: #834
      ---
       .../support/MongodbDocumentSerializer.java    | 58 ++++++++++++++-----
       .../SpringDataMongodbSerializerUnitTests.java | 24 ++++++++
       2 files changed, 69 insertions(+), 13 deletions(-)
      
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java
      index ffbc39d00d..216092127a 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java
      @@ -18,6 +18,7 @@
       import java.util.ArrayList;
       import java.util.Collection;
       import java.util.LinkedHashSet;
      +import java.util.LinkedList;
       import java.util.List;
       import java.util.Map;
       import java.util.regex.Pattern;
      @@ -49,6 +50,7 @@
        * @author Mark Paluch
        * @author Christoph Strobl
        * @author Mikhail Kaduchka
      + * @author Enrique Leon Molina
        * @since 2.1
        */
       abstract class MongodbDocumentSerializer implements Visitor {
      @@ -181,19 +183,43 @@ public Object visit(Operation expr, Void context) {
       			return asDocument(asDBKey(expr, 0), "");
       		} else if (op == Ops.AND) {
       
      -			Map lhs = (Map) handle(expr.getArg(0));
      -			Map rhs = (Map) handle(expr.getArg(1));
      +			List> pendingDocuments = new LinkedList<>();
      +			for (int i = 0; i < 2; i++) {
      +				Map document = (Map) handle(expr.getArg(i));
      +				if (document.keySet().size() == 1 && document.containsKey("$and")) {
      +					pendingDocuments.addAll((Collection>) document.get("$and"));
      +				} else {
      +					pendingDocuments.add(document);
      +				}
      +			}
      +
      +			List> unmergeableDocuments = new LinkedList<>();
      +
      +			List> generatedDocuments = new LinkedList<>();
      +
      +			do {
      +				Map lhs = pendingDocuments.remove(0);
       
      -			LinkedHashSet lhs2 = new LinkedHashSet<>(lhs.keySet());
      -			lhs2.retainAll(rhs.keySet());
      +				for (Map rhs : pendingDocuments) {
      +					LinkedHashSet lhs2 = new LinkedHashSet<>(lhs.keySet());
      +					lhs2.retainAll(rhs.keySet());
      +					if (lhs2.isEmpty()) {
      +						lhs.putAll(rhs);
      +					} else {
      +						unmergeableDocuments.add(rhs);
      +					}
      +				}
      +
      +				generatedDocuments.add(lhs);
      +				pendingDocuments = unmergeableDocuments;
      +				unmergeableDocuments = new LinkedList<>();
      +			} while(!pendingDocuments.isEmpty());
       
      -			if (lhs2.isEmpty()) {
      -				lhs.putAll(rhs);
      -				return lhs;
      +			if (generatedDocuments.size() == 1) {
      +				return generatedDocuments.get(0);
       			} else {
      -				List list = new ArrayList<>(2);
      -				list.add(handle(expr.getArg(0)));
      -				list.add(handle(expr.getArg(1)));
      +				List list = new ArrayList<>(expr.getArgs().size());
      +				list.addAll(generatedDocuments);
       				return asDocument("$and", list);
       			}
       
      @@ -212,9 +238,15 @@ public Object visit(Operation expr, Void context) {
       
       		} else if (op == Ops.OR) {
       
      -			List list = new ArrayList<>(2);
      -			list.add(handle(expr.getArg(0)));
      -			list.add(handle(expr.getArg(1)));
      +			List list = new LinkedList<>();
      +			for (int i = 0; i < 2; i++) {
      +				Map document = (Map) handle(expr.getArg(i));
      +				if (document.keySet().size() == 1 && document.containsKey("$or")) {
      +					list.addAll((Collection) document.get("$or"));
      +				} else {
      +					list.add(document);
      +				}
      +			}
       			return asDocument("$or", list);
       
       		} else if (op == Ops.NE) {
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java
      index 15eae62aaa..7ad95cf676 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java
      @@ -43,6 +43,7 @@
       import org.springframework.data.mongodb.repository.QPerson;
       
       import com.querydsl.core.types.Ops;
      +import com.querydsl.core.types.Predicate;
       import com.querydsl.core.types.PredicateOperation;
       import com.querydsl.core.types.dsl.BooleanExpression;
       import com.querydsl.core.types.dsl.BooleanOperation;
      @@ -57,6 +58,7 @@
        * @author Christoph Strobl
        * @author Mark Paluch
        * @author Mikhail Kaduchka
      + * @author Enrique Leon Molina
        */
       @ExtendWith(MockitoExtension.class)
       public class SpringDataMongodbSerializerUnitTests {
      @@ -174,6 +176,28 @@ public void retainsOpsInAndExpression() {
       				"{\"$and\": [{\"$or\": [{\"firstname\": \"John\"}, {\"firstname\": \"Sarah\"}]}, {\"$or\": [{\"lastname\": \"Smith\"}, {\"lastname\": \"Connor\"}]}]}"));
       	}
       
      +	@Test // DATAMONGO-2475
      +	public void chainedOrsInSameDocument() {
      +
      +		Predicate predicate = QPerson.person.firstname.eq("firstname_value").or(
      +				QPerson.person.lastname.eq("lastname_value")).or(QPerson.person.age.goe(30)).or(
      +						QPerson.person.age.loe(20)).or(QPerson.person.uniqueId.isNull());
      +
      +		assertThat(serializer.handle(predicate)).isEqualTo(Document.parse(
      +				"{\"$or\": [{\"firstname\": \"firstname_value\"}, {\"lastname\": \"lastname_value\"}, {\"age\": {\"$gte\": 30}}, {\"age\": {\"$lte\": 20}}, {\"uniqueId\": {\"$exists\": false}}]}"));
      +	}
      +
      +	@Test // DATAMONGO-2475
      +	public void chainedAndsInSameDocument() {
      +
      +		Predicate predicate = QPerson.person.firstname.eq("firstname_value").and(
      +				QPerson.person.lastname.eq("lastname_value")).and(QPerson.person.age.goe(30)).and(
      +						QPerson.person.age.loe(20)).and(QPerson.person.uniqueId.isNull());
      +
      +		assertThat(serializer.handle(predicate)).isEqualTo(Document.parse(
      +				"{\"$and\": [{\"firstname\": \"firstname_value\", \"lastname\": \"lastname_value\", \"age\": {\"$gte\": 30}, \"uniqueId\": {\"$exists\": false}}, {\"age\": {\"$lte\": 20}}]}"));
      +	}
      +
       	class Address {
       		String id;
       		String street;
      
      From 0e0d7264573fa6bf9266147c026e943ac8ad251d Mon Sep 17 00:00:00 2001
      From: Christoph Strobl 
      Date: Wed, 18 Mar 2020 09:18:27 +0100
      Subject: [PATCH 0114/1381] DATAMONGO-2475 - Polishing.
      
      Fix reduction of $and/$or operations with more than two arguments.
      
      Original Pull Request: #834
      ---
       .../support/MongodbDocumentSerializer.java    | 62 ++++++++-----------
       .../SpringDataMongodbSerializerUnitTests.java | 41 +++++++++---
       2 files changed, 60 insertions(+), 43 deletions(-)
      
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java
      index 216092127a..1b3c726f07 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java
      @@ -21,6 +21,8 @@
       import java.util.LinkedList;
       import java.util.List;
       import java.util.Map;
      +import java.util.Queue;
      +import java.util.Set;
       import java.util.regex.Pattern;
       
       import org.bson.BsonJavaScript;
      @@ -183,25 +185,16 @@ public Object visit(Operation expr, Void context) {
       			return asDocument(asDBKey(expr, 0), "");
       		} else if (op == Ops.AND) {
       
      -			List> pendingDocuments = new LinkedList<>();
      -			for (int i = 0; i < 2; i++) {
      -				Map document = (Map) handle(expr.getArg(i));
      -				if (document.keySet().size() == 1 && document.containsKey("$and")) {
      -					pendingDocuments.addAll((Collection>) document.get("$and"));
      -				} else {
      -					pendingDocuments.add(document);
      -				}
      -			}
      +			Queue> pendingDocuments = collectConnectorArgs("$and", expr);
      +			List> unmergeableDocuments = new ArrayList<>();
      +			List> generatedDocuments = new ArrayList<>();
       
      -			List> unmergeableDocuments = new LinkedList<>();
      +			while (!pendingDocuments.isEmpty()) {
       
      -			List> generatedDocuments = new LinkedList<>();
      -
      -			do {
      -				Map lhs = pendingDocuments.remove(0);
      +				Map lhs = pendingDocuments.poll();
       
       				for (Map rhs : pendingDocuments) {
      -					LinkedHashSet lhs2 = new LinkedHashSet<>(lhs.keySet());
      +					Set lhs2 = new LinkedHashSet<>(lhs.keySet());
       					lhs2.retainAll(rhs.keySet());
       					if (lhs2.isEmpty()) {
       						lhs.putAll(rhs);
      @@ -211,18 +204,11 @@ public Object visit(Operation expr, Void context) {
       				}
       
       				generatedDocuments.add(lhs);
      -				pendingDocuments = unmergeableDocuments;
      +				pendingDocuments = new LinkedList<>(unmergeableDocuments);
       				unmergeableDocuments = new LinkedList<>();
      -			} while(!pendingDocuments.isEmpty());
      -
      -			if (generatedDocuments.size() == 1) {
      -				return generatedDocuments.get(0);
      -			} else {
      -				List list = new ArrayList<>(expr.getArgs().size());
      -				list.addAll(generatedDocuments);
      -				return asDocument("$and", list);
       			}
       
      +			return generatedDocuments.size() == 1 ? generatedDocuments.get(0) : asDocument("$and", generatedDocuments);
       		} else if (op == Ops.NOT) {
       			// Handle the not's child
       			Operation subOperation = (Operation) expr.getArg(0);
      @@ -237,18 +223,7 @@ public Object visit(Operation expr, Void context) {
       			}
       
       		} else if (op == Ops.OR) {
      -
      -			List list = new LinkedList<>();
      -			for (int i = 0; i < 2; i++) {
      -				Map document = (Map) handle(expr.getArg(i));
      -				if (document.keySet().size() == 1 && document.containsKey("$or")) {
      -					list.addAll((Collection) document.get("$or"));
      -				} else {
      -					list.add(document);
      -				}
      -			}
      -			return asDocument("$or", list);
      -
      +			return asDocument("$or", collectConnectorArgs("$or", expr));
       		} else if (op == Ops.NE) {
       
       			Path path = (Path) expr.getArg(0);
      @@ -466,4 +441,19 @@ public Object visit(SubQueryExpression expr, Void context) {
       	public Object visit(ParamExpression expr, Void context) {
       		throw new UnsupportedOperationException();
       	}
      +
      +	private LinkedList> collectConnectorArgs(String operator, Operation operation) {
      +
      +		LinkedList> pendingDocuments = new LinkedList<>();
      +		for (Expression exp : operation.getArgs()) {
      +			Map document = (Map) handle(exp);
      +			if (document.keySet().size() == 1 && document.containsKey(operator)) {
      +				pendingDocuments.addAll((Collection>) document.get(operator));
      +			} else {
      +				pendingDocuments.add(document);
      +			}
      +		}
      +		return pendingDocuments;
      +
      +	}
       }
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java
      index 7ad95cf676..f6a7dc412c 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java
      @@ -20,6 +20,7 @@
       import static com.querydsl.core.types.dsl.Expressions.*;
       import static org.assertj.core.api.Assertions.*;
       
      +import java.util.Arrays;
       import java.util.Collections;
       
       import org.bson.Document;
      @@ -29,7 +30,6 @@
       import org.junit.jupiter.api.extension.ExtendWith;
       import org.mockito.Mock;
       import org.mockito.junit.jupiter.MockitoExtension;
      -
       import org.springframework.core.convert.converter.Converter;
       import org.springframework.data.convert.WritingConverter;
       import org.springframework.data.mongodb.core.convert.DbRefResolver;
      @@ -179,25 +179,52 @@ public void retainsOpsInAndExpression() {
       	@Test // DATAMONGO-2475
       	public void chainedOrsInSameDocument() {
       
      -		Predicate predicate = QPerson.person.firstname.eq("firstname_value").or(
      -				QPerson.person.lastname.eq("lastname_value")).or(QPerson.person.age.goe(30)).or(
      -						QPerson.person.age.loe(20)).or(QPerson.person.uniqueId.isNull());
      +		Predicate predicate = QPerson.person.firstname.eq("firstname_value")
      +				.or(QPerson.person.lastname.eq("lastname_value")).or(QPerson.person.age.goe(30)).or(QPerson.person.age.loe(20))
      +				.or(QPerson.person.uniqueId.isNull());
       
       		assertThat(serializer.handle(predicate)).isEqualTo(Document.parse(
       				"{\"$or\": [{\"firstname\": \"firstname_value\"}, {\"lastname\": \"lastname_value\"}, {\"age\": {\"$gte\": 30}}, {\"age\": {\"$lte\": 20}}, {\"uniqueId\": {\"$exists\": false}}]}"));
       	}
       
      +	@Test // DATAMONGO-2475
      +	public void chainedNestedOrsInSameDocument() {
      +
      +		Predicate predicate = QPerson.person.firstname.eq("firstname_value")
      +				.or(QPerson.person.lastname.eq("lastname_value")).or(QPerson.person.address.street.eq("spring"));
      +
      +		assertThat(serializer.handle(predicate)).isEqualTo(Document.parse(
      +				"{\"$or\": [{\"firstname\": \"firstname_value\"}, {\"lastname\": \"lastname_value\"}, {\"add.street\": \"spring\"}]}"));
      +	}
      +
       	@Test // DATAMONGO-2475
       	public void chainedAndsInSameDocument() {
       
      -		Predicate predicate = QPerson.person.firstname.eq("firstname_value").and(
      -				QPerson.person.lastname.eq("lastname_value")).and(QPerson.person.age.goe(30)).and(
      -						QPerson.person.age.loe(20)).and(QPerson.person.uniqueId.isNull());
      +		Predicate predicate = QPerson.person.firstname.eq("firstname_value")
      +				.and(QPerson.person.lastname.eq("lastname_value")).and(QPerson.person.age.goe(30))
      +				.and(QPerson.person.age.loe(20)).and(QPerson.person.uniqueId.isNull());
       
       		assertThat(serializer.handle(predicate)).isEqualTo(Document.parse(
       				"{\"$and\": [{\"firstname\": \"firstname_value\", \"lastname\": \"lastname_value\", \"age\": {\"$gte\": 30}, \"uniqueId\": {\"$exists\": false}}, {\"age\": {\"$lte\": 20}}]}"));
       	}
       
      +	@Test // DATAMONGO-2475
      +	void chainMultipleAndFlattensCorrectly() {
      +
      +		Document p1doc = Document.parse("{ \"$or\" : [ { \"firstname\" : \"fn\"}, { \"lastname\" : \"ln\" } ] }");
      +		Document p2doc = Document
      +				.parse("{ \"$or\" : [ { \"age\" : { \"$gte\" : 20 } }, { \"age\" : { \"$lte\" : 30} } ] }");
      +		Document p3doc = Document.parse("{ \"$or\" : [ { \"add.city\" : \"c\"}, { \"add.zipCode\" : \"0\" } ] }");
      +		Document expected = new Document("$and", Arrays.asList(p1doc, p2doc, p3doc));
      +
      +		Predicate predicate1 = QPerson.person.firstname.eq("fn").or(QPerson.person.lastname.eq("ln"));
      +		Predicate predicate2 = QPerson.person.age.goe(20).or(QPerson.person.age.loe(30));
      +		Predicate predicate3 = QPerson.person.address.city.eq("c").or(QPerson.person.address.zipCode.eq("0"));
      +		PredicateOperation testExpression = predicate(Ops.AND, predicate1, predicate2, predicate3);
      +
      +		assertThat(serializer.handle(testExpression)).isEqualTo(expected);
      +	}
      +
       	class Address {
       		String id;
       		String street;
      
      From 581961e79a51695385eeafebad24ee0ebd94b78b Mon Sep 17 00:00:00 2001
      From: Christoph Strobl 
      Date: Thu, 19 Mar 2020 10:21:17 +0100
      Subject: [PATCH 0115/1381] DATAMONGO-931 - Add support for $redact
       aggregation.
      
      We now support $redact via Aggregation.redact.
      
      Aggregation.redact(ConditionalOperators.when(Criteria.where("level").is(5))
          .then(RedactOperation.PRUNE)
          .otherwise(RedactOperation.DESCEND));
      
      Original pull request: #844.
      ---
       .../mongodb/core/aggregation/Aggregation.java |  20 ++
       .../core/aggregation/RedactOperation.java     | 239 ++++++++++++++++++
       .../aggregation/RedactOperationUnitTests.java |  94 +++++++
       3 files changed, 353 insertions(+)
       create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java
       create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java
      
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java
      index efcb26f24a..8a29c0dfc4 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java
      @@ -657,6 +657,26 @@ public static CountOperationBuilder count() {
       		return new CountOperationBuilder();
       	}
       
      +	/**
      +	 * Creates a new {@link RedactOperation} that can restrict the content of a document based on information stored
      +	 * within the document itself.
      +	 * 
      +	 * 
      +	 * 
      +	 * Aggregation.redact(ConditionalOperators.when(Criteria.where("level").is(5)) //
      +	 * 		.then(RedactOperation.PRUNE) //
      +	 * 		.otherwise(RedactOperation.DESCEND));
      +	 * 
      + * + * @param condition Any {@link AggregationExpression} that resolves to {@literal $$DESCEND}, {@literal $$PRUNE}, or + * {@literal $$KEEP}. Must not be {@literal null}. + * @return new instance of {@link RedactOperation}. Never {@literal null}. + * @since 3.0 + */ + public static RedactOperation redact(AggregationExpression condition) { + return new RedactOperation(condition); + } + /** * Creates a new {@link Fields} instance for the given field names. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java new file mode 100644 index 0000000000..0ef9914b17 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java @@ -0,0 +1,239 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import org.bson.Document; +import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.ThenBuilder; +import org.springframework.data.mongodb.core.query.CriteriaDefinition; +import org.springframework.util.Assert; + +/** + * {@link RedactOperation} allows to restrict the content of a {@link Document} based on information stored within + * itself. + * + *
      + * RedactOperation.builder() //
      + * 		.when(Criteria.where("level").is(5)) //
      + * 		.thenPrune() //
      + * 		.otherwiseDescend() //
      + * 		.build();
      + * 
      + * + * @author Christoph Strobl + * @see https://docs.mongodb.com/manual/reference/operator/aggregation/redact/ + * @since 3.0 + */ +public class RedactOperation implements AggregationOperation { + + /** + * Return fields at the current document level. Exclude embedded ones. + */ + public static final String DESCEND = "$$DESCEND"; + + /** + * Return/Keep all fields at the current document/embedded level. + */ + public static final String KEEP = "$$KEEP"; + + /** + * Exclude all fields at this current document/embedded level. + */ + public static final String PRUNE = "$$PRUNE"; + + private final AggregationExpression condition; + + /** + * Create new {@link RedactOperation}. + * + * @param condition Any {@link AggregationExpression} that resolves to {@literal $$DESCEND}, {@literal $$PRUNE}, or + * {@literal $$KEEP}. Must not be {@literal null}. + */ + public RedactOperation(AggregationExpression condition) { + + Assert.notNull(condition, "Condition must not be null!"); + this.condition = condition; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) + */ + @Override + public Document toDocument(AggregationOperationContext context) { + return new Document("$redact", condition.toDocument(context)); + } + + /** + * Obtain a new instance of {@link RedactOperationBuilder} to specify condition and outcome of the {@literal $redact} + * operation. + * + * @return new instance of {@link RedactOperationBuilder}. + */ + public static RedactOperationBuilder builder() { + return new RedactOperationBuilder(); + } + + /** + * Builder to create new instance of {@link RedactOperation}. + * + * @author Christoph Strobl + */ + public static class RedactOperationBuilder { + + private Object when; + private Object then; + private Object otherwise; + + /** + * Specify the evaluation condition. + * + * @param criteria must not be {@literal null}. + * @return this. + */ + public RedactOperationBuilder when(CriteriaDefinition criteria) { + + this.when = criteria; + return this; + } + + /** + * Specify the evaluation condition. + * + * @param condition must not be {@literal null}. + * @return this. + */ + public RedactOperationBuilder when(AggregationExpression condition) { + + this.when = condition; + return this; + } + + /** + * Specify the evaluation condition. + * + * @param condition must not be {@literal null}. + * @return this. + */ + public RedactOperationBuilder when(Document condition) { + + this.when = condition; + return this; + } + + /** + * Return fields at the current document level and exclude embedded ones if the condition is met. + * + * @return this. + */ + public RedactOperationBuilder thenDescend() { + return then(DESCEND); + } + + /** + * Return/Keep all fields at the current document/embedded level if the condition is met. + * + * @return this. + */ + public RedactOperationBuilder thenKeep() { + return then(KEEP); + } + + /** + * Exclude all fields at this current document/embedded level if the condition is met. + * + * @return this. + */ + public RedactOperationBuilder thenPrune() { + return then(PRUNE); + } + + /** + * Define the outcome (anything that resolves to {@literal $$DESCEND}, {@literal $$PRUNE}, or {@literal $$KEEP}) + * when the condition is met. + * + * @param then must not be {@literal null}. + * @return this. + */ + public RedactOperationBuilder then(Object then) { + + this.then = then; + return this; + } + + /** + * Return fields at the current document level and exclude embedded ones if the condition is not met. + * + * @return this. + */ + public RedactOperationBuilder otherwiseDescend() { + return otherwise(DESCEND); + } + + /** + * Return/Keep all fields at the current document/embedded level if the condition is not met. + * + * @return this. + */ + public RedactOperationBuilder otherwiseKeep() { + return otherwise(KEEP); + } + + /** + * Exclude all fields at this current document/embedded level if the condition is not met. + * + * @return this. + */ + public RedactOperationBuilder otherwisePrune() { + return otherwise(PRUNE); + } + + /** + * Define the outcome (anything that resolves to {@literal $$DESCEND}, {@literal $$PRUNE}, or {@literal $$KEEP}) + * when the condition is not met. + * + * @param otherwise must not be {@literal null}. + * @return this. + */ + public RedactOperationBuilder otherwise(Object otherwise) { + this.otherwise = otherwise; + return this; + } + + /** + * @return new instance of {@link RedactOperation}. + */ + public RedactOperation build() { + return new RedactOperation(when().then(then).otherwise(otherwise)); + } + + private ThenBuilder when() { + + if (when instanceof CriteriaDefinition) { + return ConditionalOperators.Cond.when((CriteriaDefinition) when); + } + if (when instanceof AggregationExpression) { + return ConditionalOperators.Cond.when((AggregationExpression) when); + } + if (when instanceof Document) { + return ConditionalOperators.Cond.when((Document) when); + } + + throw new IllegalArgumentException(String.format( + "Invalid Condition. Expected CriteriaDefinition, AggregationExpression or Document but was %s.", when)); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java new file mode 100644 index 0000000000..93b422468d --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java @@ -0,0 +1,94 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import lombok.Data; + +import java.util.Arrays; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + */ +class RedactOperationUnitTests { + + Document expected = new Document("$redact", + new Document("$cond", new Document("if", new Document("$eq", Arrays.asList("$level", 5))) + .append("then", "$$PRUNE").append("else", "$$DESCEND"))); + Document expectedMapped = new Document("$redact", + new Document("$cond", new Document("if", new Document("$eq", Arrays.asList("$le_v_el", 5))) + .append("then", "$$PRUNE").append("else", "$$DESCEND"))); + + @Test // DATAMONGO-931 + void errorsOnNullExpression() { + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new RedactOperation(null)); + } + + @Test // DATAMONGO-931 + void mapsAggregationExpressionCorrectly() { + + assertThat(new RedactOperation(ConditionalOperators.when(Criteria.where("level").is(5)) // + .then(RedactOperation.PRUNE) // + .otherwise(RedactOperation.DESCEND)).toDocument(contextFor(null))).isEqualTo(expected); + } + + @Test // DATAMONGO-931 + void mapsAggregationExpressionViaBuilderCorrectly() { + + assertThat(RedactOperation.builder().when(Criteria.where("level").is(5)) // + .thenPrune() // + .otherwiseDescend().build().toDocument(contextFor(null))).isEqualTo(expected); + } + + @Test // DATAMONGO-931 + void mapsTypedAggregationExpressionCorrectly() { + + assertThat(new RedactOperation(ConditionalOperators.when(Criteria.where("level").is(5)) // + .then(RedactOperation.PRUNE) // + .otherwise(RedactOperation.DESCEND)).toDocument(contextFor(DomainType.class))).isEqualTo(expectedMapped); + } + + @Data + static class DomainType { + + @Field("le_v_el") String level; + } + + private static AggregationOperationContext contextFor(@Nullable Class type) { + + if (type == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + MappingMongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, + new MongoMappingContext()); + mongoConverter.afterPropertiesSet(); + + return new TypeBasedAggregationOperationContext(type, mongoConverter.getMappingContext(), + new QueryMapper(mongoConverter)).continueOnMissingFieldReference(); + } +} From c9da0a75ffecc43404b19bb3be9e43d1a18dad23 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 20 Mar 2020 14:39:58 +0100 Subject: [PATCH 0116/1381] DATAMONGO-931 - Polishing. Reformat code. Add private constructor to prevent unwanted instantiation. Original pull request: #844. --- .../mongodb/core/aggregation/RedactOperation.java | 12 ++++++++---- .../core/aggregation/RedactOperationUnitTests.java | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java index 0ef9914b17..2bc77d3580 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java @@ -23,7 +23,7 @@ /** * {@link RedactOperation} allows to restrict the content of a {@link Document} based on information stored within * itself. - * + * *
        * RedactOperation.builder() //
        * 		.when(Criteria.where("level").is(5)) //
      @@ -89,7 +89,7 @@ public static RedactOperationBuilder builder() {
       
       	/**
       	 * Builder to create new instance of {@link RedactOperation}.
      -	 * 
      +	 *
       	 * @author Christoph Strobl
       	 */
       	public static class RedactOperationBuilder {
      @@ -98,9 +98,13 @@ public static class RedactOperationBuilder {
       		private Object then;
       		private Object otherwise;
       
      +		private RedactOperationBuilder() {
      +
      +		}
      +
       		/**
       		 * Specify the evaluation condition.
      -		 * 
      +		 *
       		 * @param criteria must not be {@literal null}.
       		 * @return this.
       		 */
      @@ -204,7 +208,7 @@ public RedactOperationBuilder otherwisePrune() {
       		/**
       		 * Define the outcome (anything that resolves to {@literal $$DESCEND}, {@literal $$PRUNE}, or {@literal $$KEEP})
       		 * when the condition is not met.
      -		 * 
      +		 *
       		 * @param otherwise must not be {@literal null}.
       		 * @return this.
       		 */
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java
      index 93b422468d..1e9946973d 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/RedactOperationUnitTests.java
      @@ -32,6 +32,8 @@
       import org.springframework.lang.Nullable;
       
       /**
      + * Unit tests for {@link RedactOperation}.
      + *
        * @author Christoph Strobl
        */
       class RedactOperationUnitTests {
      
      From e9c9938016362eccd885f42e6bd54b58571aae50 Mon Sep 17 00:00:00 2001
      From: Christoph Strobl 
      Date: Mon, 23 Mar 2020 09:18:07 +0100
      Subject: [PATCH 0117/1381] DATAMONGO-2498 - Upgrade to MongoDB 4.0.1 Drivers.
      
      ---
       pom.xml | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)
      
      diff --git a/pom.xml b/pom.xml
      index 9d4d60f25a..78d003846a 100644
      --- a/pom.xml
      +++ b/pom.xml
      @@ -27,7 +27,7 @@
       		multi
       		spring-data-mongodb
       		2.3.0.BUILD-SNAPSHOT
      -		4.0.0
      +		4.0.1
       		${mongo}
       		1.19
       	
      
      From 7a7f7c942ddab2c9ebffcea1459c75d9de8e7b67 Mon Sep 17 00:00:00 2001
      From: Heesu Jung 
      Date: Wed, 12 Jun 2019 14:52:43 +0900
      Subject: [PATCH 0118/1381] DATAMONGO-2300 - Add check rawType is null in
       readMap.
      
      Original Pull Request: #763
      ---
       .../core/convert/MappingMongoConverter.java   |  3 ++-
       .../MappingMongoConverterUnitTests.java       | 21 ++++++++++++++++++-
       2 files changed, 22 insertions(+), 2 deletions(-)
      
      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 51306aec42..49defcd773 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
      @@ -94,6 +94,7 @@
        * @author Jordi Llach
        * @author Mark Paluch
        * @author Roman Puchkovskiy
      + * @author Heesu Jung
        */
       public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
       
      @@ -1191,7 +1192,7 @@ protected Map readMap(TypeInformation type, Bson bson, Object
       				map.put(key, read(defaultedValueType, (BasicDBObject) value, path));
       			} else if (value instanceof DBRef) {
       				map.put(key, DBRef.class.equals(rawValueType) ? value
      -						: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType));
      +						: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType != null ? rawValueType : ClassTypeInformation.OBJECT.getType()));
       			} else if (value instanceof List) {
       				map.put(key, readCollectionOrArray(valueType != null ? valueType : ClassTypeInformation.LIST,
       						(List) value, path));
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
      index cdc0a02b43..c4950c05a3 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
      @@ -80,6 +80,7 @@
       import org.springframework.data.mongodb.core.mapping.TextScore;
       import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback;
       import org.springframework.data.util.ClassTypeInformation;
      +import org.springframework.data.util.TypeInformation;
       import org.springframework.test.util.ReflectionTestUtils;
       
       import com.mongodb.BasicDBList;
      @@ -95,6 +96,7 @@
        * @author Christoph Strobl
        * @author Mark Paluch
        * @author Roman Puchkovskiy
      + * @author Heesu Jung
        */
       @ExtendWith(MockitoExtension.class)
       public class MappingMongoConverterUnitTests {
      @@ -2159,11 +2161,28 @@ public void resolveDBRefMapValueShouldInvokeCallbacks() {
       		org.bson.Document document = new org.bson.Document("personMap", refMap);
       
       		DBRefWrapper result = converter.read(DBRefWrapper.class, document);
      -		
      +
       		verify(afterConvertCallback).onAfterConvert(eq(result.personMap.get("foo")),
       				eq(new org.bson.Document()), any());
       	}
       
      +	@Test // DATAMONGO-2300
      +	public void readAndConvertDBRefNestedByMapCorrectly() {
      +
      +		org.bson.Document cluster = new org.bson.Document("_id", 100L);
      +		DBRef dbRef = new DBRef("clusters", 100L);
      +
      +		org.bson.Document data = new org.bson.Document("_id", 3L);
      +		data.append("cluster", dbRef);
      +
      +		MappingMongoConverter spyConverter = spy(converter);
      +		Mockito.doReturn(cluster).when(spyConverter).readRef(dbRef);
      +
      +		Map result = spyConverter.readMap(ClassTypeInformation.MAP, data, ObjectPath.ROOT);
      +
      +		assertThat(((LinkedHashMap) result.get("cluster")).get("_id")).isEqualTo(100L);
      +	}
      +
       	static class GenericType {
       		T content;
       	}
      
      From 44913abd808f7307153d4b316b342fcfdb11a700 Mon Sep 17 00:00:00 2001
      From: Christoph Strobl 
      Date: Fri, 20 Mar 2020 11:22:38 +0100
      Subject: [PATCH 0119/1381] DATAMONGO-2300 - Polishing.
      
      Move null check to event publishing logic.
      
      Original Pull Request: #763
      ---
       .../mongodb/core/convert/MappingMongoConverter.java    | 10 +++++-----
       .../core/convert/MappingMongoConverterUnitTests.java   |  5 +----
       2 files changed, 6 insertions(+), 9 deletions(-)
      
      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 49defcd773..a23e4849a5 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
      @@ -37,7 +37,6 @@
       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;
      @@ -1192,7 +1191,7 @@ protected Map readMap(TypeInformation type, Bson bson, Object
       				map.put(key, read(defaultedValueType, (BasicDBObject) value, path));
       			} else if (value instanceof DBRef) {
       				map.put(key, DBRef.class.equals(rawValueType) ? value
      -						: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType != null ? rawValueType : ClassTypeInformation.OBJECT.getType()));
      +						: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType));
       			} else if (value instanceof List) {
       				map.put(key, readCollectionOrArray(valueType != null ? valueType : ClassTypeInformation.LIST,
       						(List) value, path));
      @@ -1596,7 +1595,7 @@ private  T potentiallyReadOrResolveDbRef(@Nullable DBRef dbref, TypeInformati
       
       	@Nullable
       	private  T readAndConvertDBRef(@Nullable DBRef dbref, TypeInformation type, ObjectPath path,
      -			final Class rawType) {
      +			@Nullable Class rawType) {
       
       		List result = bulkReadAndConvertDBRefs(Collections.singletonList(dbref), type, path, rawType);
       		return CollectionUtils.isEmpty(result) ? null : result.iterator().next();
      @@ -1619,7 +1618,7 @@ private void bulkReadAndConvertDBRefMapIntoTarget(TypeInformation valueType,
       
       	@SuppressWarnings("unchecked")
       	private  List bulkReadAndConvertDBRefs(List dbrefs, TypeInformation type, ObjectPath path,
      -			final Class rawType) {
      +			@Nullable Class rawType) {
       
       		if (CollectionUtils.isEmpty(dbrefs)) {
       			return Collections.emptyList();
      @@ -1635,7 +1634,8 @@ private  List bulkReadAndConvertDBRefs(List dbrefs, TypeInformation
       		for (Document document : referencedRawDocuments) {
       
       			if (document != null) {
      -				maybeEmitEvent(new AfterLoadEvent<>(document, (Class) rawType, collectionName));
      +				maybeEmitEvent(
      +						new AfterLoadEvent<>(document, (Class) (rawType != null ? rawType : Object.class), collectionName));
       			}
       
       			T target = (T) read(type, document, path);
      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
      index c4950c05a3..82a6840f9c 100644
      --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
      +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
      @@ -42,7 +42,6 @@
       import org.mockito.Mock;
       import org.mockito.Mockito;
       import org.mockito.junit.jupiter.MockitoExtension;
      -
       import org.springframework.aop.framework.ProxyFactory;
       import org.springframework.beans.ConversionNotSupportedException;
       import org.springframework.beans.factory.annotation.Value;
      @@ -80,7 +79,6 @@
       import org.springframework.data.mongodb.core.mapping.TextScore;
       import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback;
       import org.springframework.data.util.ClassTypeInformation;
      -import org.springframework.data.util.TypeInformation;
       import org.springframework.test.util.ReflectionTestUtils;
       
       import com.mongodb.BasicDBList;
      @@ -2162,8 +2160,7 @@ public void resolveDBRefMapValueShouldInvokeCallbacks() {
       
       		DBRefWrapper result = converter.read(DBRefWrapper.class, document);
       
      -		verify(afterConvertCallback).onAfterConvert(eq(result.personMap.get("foo")),
      -				eq(new org.bson.Document()), any());
      +		verify(afterConvertCallback).onAfterConvert(eq(result.personMap.get("foo")), eq(new org.bson.Document()), any());
       	}
       
       	@Test // DATAMONGO-2300
      
      From 6366d3cec12b32c6dcfca7e90626868539bdda38 Mon Sep 17 00:00:00 2001
      From: Mark Paluch 
      Date: Wed, 25 Mar 2020 10:45:28 +0100
      Subject: [PATCH 0120/1381] DATAMONGO-2485 - Updated changelog.
      
      ---
       src/main/resources/changelog.txt | 10 ++++++++++
       1 file changed, 10 insertions(+)
      
      diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt
      index 659de9ed2e..34ccdc2d98 100644
      --- a/src/main/resources/changelog.txt
      +++ b/src/main/resources/changelog.txt
      @@ -1,6 +1,15 @@
       Spring Data MongoDB Changelog
       =============================
       
      +Changes in version 2.2.6.RELEASE (2020-03-25)
      +---------------------------------------------
      +* DATAMONGO-2497 - Update documentation regarding @Transient properties usage in the persistence constructor.
      +* DATAMONGO-2488 - KeyMapper.mapPropertyName does not work for nested arrays.
      +* DATAMONGO-2485 - Release 2.2.6 (Moore SR6).
      +* DATAMONGO-2445 - Deprecate ReactiveGridFs methods using AsyncInputStream.
      +* DATAMONGO-2300 - Can't read and convert DBRef when the type is Map.
      +
      +
       Changes in version 3.0.0.M4 (2020-03-11)
       ----------------------------------------
       * DATAMONGO-2491 - Adapt to Mockito 3.3 changes.
      @@ -2950,3 +2959,4 @@ Repository
       
       
       
      +
      
      From 7bac739146396f3b691c1ed1d5bd2e8b27f0460f Mon Sep 17 00:00:00 2001
      From: Oliver Drotbohm 
      Date: Thu, 26 Mar 2020 14:36:41 +0100
      Subject: [PATCH 0121/1381] DATAMONGO-2501 - Upgrade to Querydsl 4.3.
      
      Adapted to changes in the APT APIs.
      ---
       .../repository/support/MongoAnnotationProcessor.java        | 6 +++---
       1 file changed, 3 insertions(+), 3 deletions(-)
      
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java
      index 9849dea3a2..58e3cb5985 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java
      @@ -54,9 +54,9 @@ protected Configuration createConfiguration(@Nullable RoundEnvironment roundEnv)
       
       		processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Running " + getClass().getSimpleName());
       
      -		DefaultConfiguration configuration = new DefaultConfiguration(roundEnv, processingEnv.getOptions(),
      -				Collections.emptySet(), QueryEntities.class, Document.class, QuerySupertype.class,
      -				QueryEmbeddable.class, QueryEmbedded.class, QueryTransient.class);
      +		DefaultConfiguration configuration = new DefaultConfiguration(processingEnv, roundEnv, Collections.emptySet(),
      +				QueryEntities.class, Document.class, QuerySupertype.class, QueryEmbeddable.class, QueryEmbedded.class,
      +				QueryTransient.class);
       		configuration.setUnknownAsEmbedded(true);
       
       		return configuration;
      
      From 29f05af733ee97f5abbb319a3f8a23255c9c6717 Mon Sep 17 00:00:00 2001
      From: Christoph Strobl 
      Date: Tue, 24 Mar 2020 07:50:44 +0100
      Subject: [PATCH 0122/1381] DATAMONGO-2477 - Disable auto index creation by
       default.
      
      Original pull request: #845.
      ---
       .../config/MappingMongoConverterParser.java   | 10 ++++
       .../config/MongoConfigurationSupport.java     |  6 +--
       .../core/mapping/MongoMappingContext.java     |  7 +--
       .../data/mongodb/config/spring-mongo-3.0.xsd  | 10 ++++
       .../config/AbstractIntegrationTests.java      |  5 ++
       .../mongodb/core/MongoTemplateUnitTests.java  |  1 +
       .../core/ReactiveMongoTemplateIndexTests.java |  8 ++-
       .../core/index/IndexingIntegrationTests.java  |  5 ++
       .../core/mapping/GeoIndexedAppConfig.java     |  5 ++
       .../mongodb/core/mapping/MappingTests.java    | 14 +++++-
       .../ReactiveMongoRepositoryTests.java         |  5 ++
       ...MongoNamespaceIntegrationTests-context.xml |  2 +
       src/main/asciidoc/reference/mapping.adoc      |  6 +--
       src/main/asciidoc/upgrading.adoc              | 50 ++++++++++++++++++-
       14 files changed, 120 insertions(+), 14 deletions(-)
      
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java
      index adbf2e771d..767c03e3af 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java
      @@ -96,6 +96,9 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
       		String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
       		id = StringUtils.hasText(id) ? id : DEFAULT_CONVERTER_BEAN_NAME;
       
      +		String autoIndexCreation = element.getAttribute("auto-index-creation");
      +		boolean autoIndexCreationEnabled = StringUtils.hasText(autoIndexCreation) && Boolean.valueOf(autoIndexCreation);
      +
       		parserContext.pushContainingComponent(new CompositeComponentDefinition("Mapping Mongo Converter", element));
       
       		BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
      @@ -199,6 +202,11 @@ private RuntimeBeanReference getValidator(Object source, ParserContext parserCon
       
       	public static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
       			@Nullable BeanDefinition conversionsDefinition, @Nullable String converterId) {
      +		return potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, converterId, false);
      +	}
      +
      +	public static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
      +			@Nullable BeanDefinition conversionsDefinition, @Nullable String converterId, boolean autoIndexCreation) {
       
       		String ctxRef = element.getAttribute("mapping-context-ref");
       
      @@ -226,6 +234,8 @@ public static String potentiallyCreateMappingContext(Element element, ParserCont
       			mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition);
       		}
       
      +		mappingContextBuilder.addPropertyValue("autoIndexCreation", autoIndexCreation);
      +
       		parseFieldNamingStrategy(element, parserContext.getReaderContext(), mappingContextBuilder);
       
       		ctxRef = converterId == null || DEFAULT_CONVERTER_BEAN_NAME.equals(converterId) ? MAPPING_CONTEXT_BEAN_NAME
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java
      index efef317d85..41870bdca5 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java
      @@ -199,12 +199,12 @@ protected FieldNamingStrategy fieldNamingStrategy() {
       	 * Configure whether to automatically create indices for domain types by deriving the
       	 * {@link org.springframework.data.mongodb.core.index.IndexDefinition} from the entity or not.
       	 *
      -	 * @return {@literal true} by default. 
      - * INFO: As of 3.x the default will be set to {@literal false}. + * @return {@literal false} by default.
      + * INFO: As of 3.x the default will is set to {@literal false} was {@literal true} in 2.x. * @since 2.2 */ protected boolean autoIndexCreation() { - return true; + return false; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index b55fb3cfa4..170ba47d77 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -43,7 +43,7 @@ public class MongoMappingContext extends AbstractMappingContextNOTE:Index creation should happen at a well-defined time that is ideally controlled by the * application itself. * - * @return {@literal true} when auto-index creation is enabled; {@literal false} otherwise. + * @return {@literal true} when auto-index creation is enabled; {@literal false} otherwise.
      + * INFO: As of 3.x the default will is set to {@literal false} was {@literal true} in 2.x. * @since 2.2 * @see org.springframework.data.mongodb.core.index.Indexed */ @@ -121,7 +122,7 @@ public boolean isAutoIndexCreation() { * NOTE:Index creation should happen at a well-defined time that is ideally controlled by the * application itself. * - * @param autoCreateIndexes set to {@literal false} to disable auto-index creation. + * @param autoCreateIndexes set to {@literal true} to enable auto-index creation. * @since 2.2 * @see org.springframework.data.mongodb.core.index.Indexed */ diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd index e670b66cde..8a6f39bb7a 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd @@ -224,6 +224,16 @@ The base package in which to scan for entities annotated with @Document + + + + Enable/Disable index creation for annotated properties/entities. + + + + + + diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 29b24dd5c0..fe75ae5a6f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -62,6 +62,11 @@ public MongoClient mongoClient() { protected Set> getInitialEntitySet() throws ClassNotFoundException { return Collections.emptySet(); } + + @Override + protected boolean autoIndexCreation() { + return true; + } } @Autowired MongoOperations operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 44dfead8b6..da6a16c6a4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -206,6 +206,7 @@ void beforeEach() { when(distinctIterable.into(any())).thenReturn(Collections.emptyList()); this.mappingContext = new MongoMappingContext(); + mappingContext.setAutoIndexCreation(true); mappingContext.afterPropertiesSet(); this.converter = spy(new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index b1f678bda7..07757dc25f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -19,6 +19,9 @@ import static org.springframework.data.mongodb.test.util.Assertions.*; import lombok.Data; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; @@ -66,7 +69,10 @@ public class ReactiveMongoTemplateIndexTests { void setUp() { factory = new SimpleReactiveMongoDatabaseFactory(client, "reactive-template-index-tests"); - template = new ReactiveMongoTemplate(factory); + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.setAutoIndexCreation(true); + template = new ReactiveMongoTemplate(factory, new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)); + MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "person", client); MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "indexfail", client); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index acfab7bfb8..fb269c0c17 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -95,6 +95,11 @@ TimeoutResolver myTimeoutResolver() { protected Set> getInitialEntitySet() throws ClassNotFoundException { return Collections.emptySet(); } + + @Override + protected boolean autoIndexCreation() { + return true; + } } @AfterEach diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java index 966f146846..63667b41c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java @@ -55,4 +55,9 @@ public LoggingEventListener mappingEventsListener() { protected Set> getInitialEntitySet() throws ClassNotFoundException { return Collections.emptySet(); } + + @Override + protected boolean autoIndexCreation() { + return true; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java index f6addcd40d..153e653f23 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java @@ -40,6 +40,9 @@ import org.springframework.data.mongodb.MongoCollectionUtils; import org.springframework.data.mongodb.core.CollectionCallback; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.Client; @@ -186,7 +189,10 @@ public void testWriteEntity() { @SuppressWarnings({ "unchecked", "rawtypes" }) public void testUniqueIndex() { - MongoTemplate template = new MongoTemplate(client, DB_NAME); + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.setAutoIndexCreation(true); + + MongoTemplate template = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, DB_NAME), new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)); Address addr = new Address(); addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" }); @@ -227,7 +233,11 @@ public void testPrimitivesAndCustomCollectionName() { @Test public void testIndexesCreatedInRightCollection() { - MongoTemplate template = new MongoTemplate(client, DB_NAME); + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.setAutoIndexCreation(true); + + MongoTemplate template = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, DB_NAME), new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)); + CustomCollectionWithIndex ccwi = new CustomCollectionWithIndex("test"); template.insert(ccwi); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index 9c08e352bd..ef388005e9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -131,6 +131,11 @@ ReactiveContactRepository reactiveContactRepository(ReactiveMongoRepositoryFacto ReactiveCappedCollectionRepository reactiveCappedCollectionRepository(ReactiveMongoRepositoryFactory factory) { return factory.getRepository(ReactiveCappedCollectionRepository.class); } + + @Override + protected boolean autoIndexCreation() { + return true; + } } @BeforeAll diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml index 839d6b2f44..f335c637f8 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml @@ -18,6 +18,8 @@ + + diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index d0bcf96dc7..eb690a34d3 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -392,7 +392,7 @@ Automatic index creation is only done for types annotated with `@Document`. [NOTE] ==== -To turn automatic index creation _OFF_ please override `autoIndexCreation()` in your configuration. +To turn automatic index creation _ON_ please override `autoIndexCreation()` in your configuration. [source,java] ---- @Configuration @@ -400,7 +400,7 @@ public class Config extends AbstractMongoClientConfiguration { @Override public boolean autoIndexCreation() { - return false; + return true; } // ... @@ -408,7 +408,7 @@ public class Config extends AbstractMongoClientConfiguration { ---- ==== -IMPORTANT: Automatic index creation will be turned _OFF_ by default with the release of 3.x. +IMPORTANT: Automatic index creation is turned _OFF_ by default as of the release of 3.x. We recommend index creation to happen either out of band or as part of the application startup using `IndexOperations`. diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index d2111515b6..f695e0d064 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -148,6 +148,52 @@ Element | Comment == Other Changes +=== Auto Index Creation + +Annotation based index creation is now turned **OFF** by default and needs to be enabled eg. when relying on `@GeoSpatialIndexed`. + +.Enable Auto Index Creation +==== + +.XML Namespace +[source,xml] +---- + <1> +---- + +.Java Config +[source,java] +---- +@Configuration +public class Config extends AbstractMongoClientConfiguration { + + @Override + protected boolean autoIndexCreation() { <2> + return true; + } + + // ... +} +---- + +.Programmatic +[source,java] +---- +MongoDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(...); +DefaultDbRefResolver dbRefResolver = new DefaultDbRefResolver(dbFactory); + +MongoMappingContext mappingContext = new MongoMappingContext(); +mappingContext.setAutoIndexCreation(true); <3> +// ... +mappingContext.afterPropertiesSet(); + +MongoTemplate template = new MongoTemplate(dbFactory, new MappingMongoConverter(dbRefResolver, mappingContext)); +---- +<1> Use the XML namespace attribute `auto-index-creation` on `mapping-converter`. +<2> Overrride `autoIndexCreation` via `AbstractMongoClientConfiguration` or `AbstractReactiveMongoClientConfiguration`. +<3> Set the flag on `MongoMappingContext`. +==== + === UUID Types The MongoDB UUID representation can now be configured with different formats. @@ -157,8 +203,8 @@ This has to be done via `MongoClientSettings` as shown in the snippet below. ==== [source,java] ---- - -static class Config extends AbstractMongoClientConfiguration { +@Configuration +public class Config extends AbstractMongoClientConfiguration { @Override public void configureClientSettings(MongoClientSettings.Builder builder) { From 1118df555058bb42ed5a9b5dd427fde2eb0ce9cc Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 26 Mar 2020 14:08:13 +0100 Subject: [PATCH 0123/1381] DATAMONGO-2477 - Polishing. Remove warn log for auto-index creation. Remove unused fields. Document index creation in reference documentation. Original pull request: #845. --- .../config/MongoConfigurationSupport.java | 2 +- .../mongodb/core/index/JustOnceLogger.java | 84 ------------------- .../MongoPersistentEntityIndexCreator.java | 2 - ...tiveMongoPersistentEntityIndexCreator.java | 2 - .../core/mapping/MongoMappingContext.java | 3 - src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/reference/mapping.adoc | 64 +++++++++++++- src/main/asciidoc/upgrading.adoc | 9 +- 8 files changed, 67 insertions(+), 100 deletions(-) delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index 41870bdca5..9b094e537a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -200,7 +200,7 @@ protected FieldNamingStrategy fieldNamingStrategy() { * {@link org.springframework.data.mongodb.core.index.IndexDefinition} from the entity or not. * * @return {@literal false} by default.
      - * INFO: As of 3.x the default will is set to {@literal false} was {@literal true} in 2.x. + * INFO: As of 3.x the default is set to {@literal false}; In 2.x it was {@literal true}. * @since 2.2 */ protected boolean autoIndexCreation() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java deleted file mode 100644 index 109270ec04..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2019-2020 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 - * - * https://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.index; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentSkipListSet; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author Christoph Strobl - * @since 2.2 - */ -class JustOnceLogger { - - private static final Map> KNOWN_LOGS = new ConcurrentHashMap<>(); - private static final String AUTO_INDEX_CREATION_CONFIG_CHANGE; - - static { - AUTO_INDEX_CREATION_CONFIG_CHANGE = "Automatic index creation will be disabled by default as of Spring Data MongoDB 3.x." - + System.lineSeparator() - + "\tPlease use 'MongoMappingContext#setAutoIndexCreation(boolean)' or override 'MongoConfigurationSupport#autoIndexCreation()' to be explicit." - + System.lineSeparator() - + "\tHowever, we recommend setting up indices manually in an application ready block. You may use index derivation there as well." - + System.lineSeparator() + System.lineSeparator() // - + "\t> -----------------------------------------------------------------------------------------" - + System.lineSeparator() // - + "\t> @EventListener(ApplicationReadyEvent.class)" + System.lineSeparator() // - + "\t> public void initIndicesAfterStartup() {" + System.lineSeparator() // - + "\t>" + System.lineSeparator() // - + "\t> IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);" + System.lineSeparator()// - + "\t>" + System.lineSeparator() // - + "\t> IndexResolver resolver = new MongoPersistentEntityIndexResolver(mongoMappingContext);" - + System.lineSeparator() // - + "\t> resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);" + System.lineSeparator() // - + "\t> }" + System.lineSeparator() // - + "\t> -----------------------------------------------------------------------------------------" - + System.lineSeparator(); - } - - static void logWarnIndexCreationConfigurationChange(String loggerName) { - warnOnce(loggerName, AUTO_INDEX_CREATION_CONFIG_CHANGE); - } - - static void warnOnce(String loggerName, String message) { - - Logger logger = LoggerFactory.getLogger(loggerName); - if (!logger.isWarnEnabled()) { - return; - } - - if (!KNOWN_LOGS.containsKey(loggerName)) { - - KNOWN_LOGS.put(loggerName, new ConcurrentSkipListSet<>(Collections.singleton(message))); - logger.warn(message); - } else { - - Set messages = KNOWN_LOGS.get(loggerName); - if (messages.contains(message)) { - return; - } - - messages.add(message); - logger.warn(message); - } - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java index ec910a8680..172c10590f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java @@ -139,8 +139,6 @@ private void checkForAndCreateIndexes(MongoPersistentEntity entity) { for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(entity.getTypeInformation())) { - JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName()); - IndexDefinitionHolder indexToCreate = indexDefinition instanceof IndexDefinitionHolder ? (IndexDefinitionHolder) indexDefinition : new IndexDefinitionHolder("", indexDefinition, collection); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java index 1bed0a797f..b4e7337150 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java @@ -142,8 +142,6 @@ private Mono checkForAndCreateIndexes(MongoPersistentEntity entity) { Mono createIndex(IndexDefinitionHolder indexDefinition) { - JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName()); - return operationsProvider.indexOps(indexDefinition.getCollection()).ensureIndex(indexDefinition) // .onErrorResume(ReactiveMongoPersistentEntityIndexCreator::isDataIntegrityViolation, e -> translateException(e, indexDefinition)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index 170ba47d77..239fb4b1cf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -42,7 +42,6 @@ public class MongoMappingContext extends AbstractMappingContext BasicMongoPersistentEntity createPersistentEntity(TypeInformati public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { super.setApplicationContext(applicationContext); - - this.context = applicationContext; } /** diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index e6ab1684d3..e6f2a38734 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,6 +5,7 @@ == What's New in Spring Data MongoDB 3.0 * Upgrade to MongoDB Driver 4.0. See <> for further details. +* <> is now **disabled** by default. * Support for <>. * Removal of `_id` flattening for composite Id's when using `MongoTemplate` aggregations. * Apply pagination when using GridFS `find(Query)`. diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index eb690a34d3..8e2736f2cf 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -390,6 +390,64 @@ public class Person { IMPORTANT: The `@Id` annotation tells the mapper which property you want to use for the MongoDB `_id` property, and the `@Indexed` annotation tells the mapping framework to call `createIndex(…)` on that property of your document, making searches faster. Automatic index creation is only done for types annotated with `@Document`. +[[mapping.index-creation]] +=== Index Creation + +Spring Data MongoDB can automatically create indexes for entity types annotated with `@Document`. Index creation must be explicitly enabled since version 3.0 to prevent undesired effects with collection lifecyle and performance impact. Indexes are automatically created for the initial entity set on application startup and when accessing an entity type for the first time while the application runs. + +We generally recommend explicit index creation for application-based control of indexes as Spring Data cannot automatically create indexes for collections that were recreated while the application was running. + +`IndexResolver` provides an abstraction for programmatic index definition creation if you want to make use of `@Indexed` annotations such as `@GeoSpatialIndexed`, `@TextIndexed`, `@CompoundIndex`. You can use index definitions with `IndexOperations` to create indexes. A good point in time for index creation is on application startup, specifically after the application context was refreshed, triggered by observing `ContextRefreshedEvent`. This event guarantees that the context is fully initialized. Note that at this time other components, especially bean factories might have access to the MongoDB database. + +.Programmatic Index Creation for a single Domain Type +==== +[source,java] +---- +class MyListener { + + @EventListener(ContextRefreshedEvent.class) + public void initIndicesAfterStartup() { + + MappingContext, MongoPersistentProperty> mappingContext = mongoTemplate + .getConverter().getMappingContext(); + + IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext); + + IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class); + resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex); + } +} +---- +==== + +.Programmatic Index Creation for all Initial Entities +==== +[source,java] +---- +class MyListener{ + + @EventListener(ContextRefreshedEvent.class) + public void initIndicesAfterStartup() { + + MappingContext, MongoPersistentProperty> mappingContext = mongoTemplate + .getConverter().getMappingContext(); + + // consider only entities that are annotated with @Document + mappingContext.getPersistentEntities() + .stream() + .filter(it -> it.isAnnotationPresent(Document.class)) + .forEach(it -> { + + IndexOperations indexOps = mongoTemplate.indexOps(it.getType()); + resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex); + }); + } +} +---- +==== + +Alternatively, if you want to ensure index and collection presence before any component is able to access your database from your application, declare a `@Bean` method for `MongoTemplate` and include the code from above before returning the `MongoTemplate` object. + [NOTE] ==== To turn automatic index creation _ON_ please override `autoIndexCreation()` in your configuration. @@ -403,14 +461,12 @@ public class Config extends AbstractMongoClientConfiguration { return true; } - // ... +// ... } ---- ==== -IMPORTANT: Automatic index creation is turned _OFF_ by default as of the release of 3.x. -We recommend index creation to happen either out of band or as part of the application startup using -`IndexOperations`. +IMPORTANT: Automatic index creation is turned _OFF_ by default as of version 3.0. [[mapping-usage-annotations]] === Mapping Annotation Overview diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index f695e0d064..c89376607a 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -151,6 +151,7 @@ Element | Comment === Auto Index Creation Annotation based index creation is now turned **OFF** by default and needs to be enabled eg. when relying on `@GeoSpatialIndexed`. +Please refer to <> on how to create indexes programmatically. .Enable Auto Index Creation ==== @@ -158,7 +159,7 @@ Annotation based index creation is now turned **OFF** by default and needs to be .XML Namespace [source,xml] ---- - <1> + <1> ---- .Java Config @@ -168,7 +169,7 @@ Annotation based index creation is now turned **OFF** by default and needs to be public class Config extends AbstractMongoClientConfiguration { @Override - protected boolean autoIndexCreation() { <2> + protected boolean autoIndexCreation() { <2> return true; } @@ -183,14 +184,14 @@ MongoDatabaseFactory dbFactory = new SimpleMongoClientDatabaseFactory(...); DefaultDbRefResolver dbRefResolver = new DefaultDbRefResolver(dbFactory); MongoMappingContext mappingContext = new MongoMappingContext(); -mappingContext.setAutoIndexCreation(true); <3> +mappingContext.setAutoIndexCreation(true); <3> // ... mappingContext.afterPropertiesSet(); MongoTemplate template = new MongoTemplate(dbFactory, new MappingMongoConverter(dbRefResolver, mappingContext)); ---- <1> Use the XML namespace attribute `auto-index-creation` on `mapping-converter`. -<2> Overrride `autoIndexCreation` via `AbstractMongoClientConfiguration` or `AbstractReactiveMongoClientConfiguration`. +<2> Override `autoIndexCreation` via `AbstractMongoClientConfiguration` or `AbstractReactiveMongoClientConfiguration`. <3> Set the flag on `MongoMappingContext`. ==== From ffba352e152d62a6b24d89aef2a416cb4c011c70 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 16 Mar 2020 10:45:11 +0100 Subject: [PATCH 0124/1381] DATAMONGO-625 - Add support for GridFS with predefined id. We now support storing GridFS content with predefined id, which allows to replace an existing resource instead of having to delete and reupload it. Original pull request: #842. --- .../data/mongodb/gridfs/GridFsObject.java | 167 ++++++++++++++ .../data/mongodb/gridfs/GridFsOperations.java | 46 +++- .../data/mongodb/gridfs/GridFsResource.java | 37 ++- .../data/mongodb/gridfs/GridFsTemplate.java | 46 ++-- .../data/mongodb/gridfs/GridFsUpload.java | 214 ++++++++++++++++++ .../gridfs/ReactiveGridFsOperations.java | 35 ++- .../gridfs/ReactiveGridFsResource.java | 61 ++++- .../gridfs/ReactiveGridFsTemplate.java | 34 +-- .../mongodb/gridfs/ReactiveGridFsUpload.java | 205 +++++++++++++++++ .../data/mongodb/util/BsonUtils.java | 63 ++++++ .../GridFsTemplateIntegrationTests.java | 24 ++ .../gridfs/ReactiveGridFsTemplateTests.java | 37 ++- .../data/mongodb/util/json/BsonUtilsTest.java | 67 ++++++ 13 files changed, 981 insertions(+), 55 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java new file mode 100644 index 0000000000..592bab9409 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java @@ -0,0 +1,167 @@ +/* + * Copyright 2020 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 + * + * https://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.gridfs; + +import org.bson.Document; +import org.springframework.lang.Nullable; + +import com.mongodb.client.gridfs.model.GridFSFile; + +/** + * A common interface when dealing with GridFs items using Spring Data.o + * + * @author Christoph Strobl + * @since 3.0 + */ +public interface GridFsObject { + + /** + * The {@link GridFSFile#getId()} value converted into its simple java type.
      + * A {@link org.bson.BsonString} will be converted to plain {@link String}. + * + * @return can be {@literal null} depending on the implementation. + */ + @Nullable + ID getFileId(); + + /** + * The filename. + * + * @return + */ + String getFilename(); + + /** + * The actual file content. + * + * @return + */ + CONTENT getContent(); + + /** + * Additional information like file metadata (eg. contentType). + * + * @return never {@literal null}. + */ + Options getOptions(); + + /** + * Additional, context relevant information. + * + * @author Christoph Strobl + */ + class Options { + + private Document metadata = new Document(); + private int chunkSize = -1; + + private Options(Document metadata, int chunkSize) { + + this.metadata = metadata; + this.chunkSize = chunkSize; + } + + /** + * Static factory to create empty options. + * + * @return new instance of {@link Options}. + */ + public static Options none() { + return new Options(new Document(), -1); + } + + /** + * Static factory method to create {@link Options} with given chunk size. + * + * @param chunkSize + * @return new instance of {@link Options}. + */ + public static Options chunked(int chunkSize) { + return new Options(new Document(), chunkSize); + } + + /** + * Static factory method to create {@link Options} with given content type. + * + * @param contentType + * @return new instance of {@link Options}. + */ + public static Options typed(String contentType) { + return new Options(new Document("_contentType", contentType), -1); + } + + /** + * Static factory method to create {@link Options} by extracting information from the given {@link GridFSFile}. + * + * @param gridFSFile can be {@literal null}, returns {@link #none()} in that case. + * @return new instance of {@link Options}. + */ + public static Options from(@Nullable GridFSFile gridFSFile) { + return gridFSFile != null ? new Options(gridFSFile.getMetadata(), gridFSFile.getChunkSize()) : none(); + } + + /** + * Set the associated content type. + * + * @param contentType must not be {@literal null}. + * @return new instance of {@link Options}. + */ + public Options contentType(String contentType) { + + Options target = new Options(new Document(metadata), chunkSize); + target.metadata.put("_contentType", contentType); + return target; + } + + /** + * @param metadata + * @return new instance of {@link Options}. + */ + public Options metadata(Document metadata) { + return new Options(metadata, chunkSize); + } + + /** + * @param chunkSize the file chunk size to use. + * @return new instance of {@link Options}. + */ + public Options chunkSize(int chunkSize) { + return new Options(metadata, chunkSize); + } + + /** + * @return never {@literal null}. + */ + public Document getMetadata() { + return metadata; + } + + /** + * @return the chunk size to use. + */ + public int getChunkSize() { + return chunkSize; + } + + /** + * @return {@literal null} if not set. + */ + @Nullable + String getContentType() { + return (String) metadata.get("_contentType"); + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index abda4e6178..5f7ee4ce91 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -22,7 +22,10 @@ import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.gridfs.GridFsUpload.GridFsUploadBuilder; import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; import com.mongodb.client.gridfs.GridFSFindIterable; @@ -45,7 +48,9 @@ public interface GridFsOperations extends ResourcePatternResolver { * @param filename must not be {@literal null} or empty. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, String filename); + default ObjectId store(InputStream content, String filename) { + return store(content, filename, null, null); + } /** * Stores the given content into a file with the given name. @@ -63,7 +68,9 @@ public interface GridFsOperations extends ResourcePatternResolver { * @param metadata can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, @Nullable Document metadata); + default ObjectId store(InputStream content, @Nullable Document metadata) { + return store(content, null, metadata); + } /** * Stores the given content into a file with the given name and content type. @@ -107,7 +114,9 @@ ObjectId store(InputStream content, @Nullable String filename, @Nullable String * @param metadata can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, @Nullable String filename, @Nullable Document metadata); + default ObjectId store(InputStream content, @Nullable String filename, @Nullable Document metadata) { + return store(content, filename, null, metadata); + } /** * Stores the given content into a file with the given name and content type using the given metadata. @@ -118,8 +127,35 @@ ObjectId store(InputStream content, @Nullable String filename, @Nullable String * @param metadata can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType, - @Nullable Document metadata); + default ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType, + @Nullable Document metadata) { + + GridFsUploadBuilder uploadBuilder = GridFsUpload.fromStream(content); + if (StringUtils.hasText(filename)) { + uploadBuilder.filename(filename); + } + if (StringUtils.hasText(contentType)) { + uploadBuilder.contentType(contentType); + } + if (!ObjectUtils.isEmpty(metadata)) { + uploadBuilder.metadata(metadata); + } + + return save(uploadBuilder.build()); + } + + /** + * Stores the given {@link GridFsObject}, likely a {@link GridFsUpload}, into into a file with given + * {@link GridFsObject#getFilename() name}. If the {@link GridFsObject#getFileId()} is set, the file will be stored + * with that id, otherwise the server auto creates a new id.
      + * + * @param upload the {@link GridFsObject} (most likely a {@link GridFsUpload}) to be stored. + * @param id type of the underlying {@link com.mongodb.client.gridfs.model.GridFSFile} + * @return the id of the stored file. Either an auto created value or {@link GridFsObject#getFileId()}, but never + * {@literal null}. + * @since 3.0 + */ + T save(GridFsObject upload); /** * Returns all files matching the given query. Note, that currently {@link Sort} criterias defined at the diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java index 2413e76858..a37ba34a06 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java @@ -23,6 +23,7 @@ import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -37,7 +38,7 @@ * @author Hartmut Lang * @author Mark Paluch */ -public class GridFsResource extends InputStreamResource { +public class GridFsResource extends InputStreamResource implements GridFsObject { static final String CONTENT_TYPE_FIELD = "_contentType"; private static final ByteArrayInputStream EMPTY_INPUT_STREAM = new ByteArrayInputStream(new byte[0]); @@ -169,6 +170,17 @@ public Object getId() { return getGridFSFile().getId(); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFileId() + */ + @Override + public Object getFileId() { + + Assert.state(exists(), () -> String.format("%s does not exist.", getDescription())); + return BsonUtils.toJavaType(getGridFSFile().getId()); + } + /** * @return the underlying {@link GridFSFile}. Can be {@literal null} if absent. * @since 2.2 @@ -195,6 +207,29 @@ public String getContentType() { .orElseThrow(() -> new MongoGridFSException("No contentType data for this GridFS file")); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getContent() + */ + @Override + public InputStream getContent() { + + try { + return getInputStream(); + } catch (IOException e) { + throw new IllegalStateException("Failed to obtain input stream for " + filename, e); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getOptions() + */ + @Override + public Options getOptions() { + return Options.from(getGridFSFile()); + } + private void verifyExists() throws FileNotFoundException { if (!exists()) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 453a565610..cf8b2211c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -29,6 +29,7 @@ import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -38,6 +39,7 @@ import com.mongodb.client.gridfs.GridFSBuckets; import com.mongodb.client.gridfs.GridFSFindIterable; import com.mongodb.client.gridfs.model.GridFSFile; +import com.mongodb.client.gridfs.model.GridFSUploadOptions; /** * {@link GridFsOperations} implementation to store content into MongoDB GridFS. @@ -85,14 +87,6 @@ public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter, this.bucket = bucket; } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String) - */ - public ObjectId store(InputStream content, String filename) { - return store(content, filename, (Object) null); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.Object) @@ -102,15 +96,6 @@ public ObjectId store(InputStream content, @Nullable Object metadata) { return store(content, null, metadata); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, com.mongodb.Document) - */ - @Override - public ObjectId store(InputStream content, @Nullable Document metadata) { - return store(content, null, metadata); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String) @@ -138,21 +123,24 @@ public ObjectId store(InputStream content, @Nullable String filename, @Nullable /* * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.Document) + * @see org.springframework.data.mongodb.gridfs.GridFsOperations#save(org.springframework.data.mongodb.gridfs.GridFsObject) */ - public ObjectId store(InputStream content, @Nullable String filename, @Nullable Document metadata) { - return this.store(content, filename, null, metadata); - } + public T save(GridFsObject upload) { - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.Document) - */ - public ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType, - @Nullable Document metadata) { + GridFSUploadOptions uploadOptions = computeUploadOptionsFor(upload.getOptions().getContentType(), + upload.getOptions().getMetadata()); + + if (upload.getOptions().getChunkSize() > 0) { + uploadOptions.chunkSizeBytes(upload.getOptions().getChunkSize()); + } + + if (upload.getFileId() == null) { + return (T) getGridFs().uploadFromStream(upload.getFilename(), upload.getContent(), uploadOptions); + } - Assert.notNull(content, "InputStream must not be null!"); - return getGridFs().uploadFromStream(filename, content, computeUploadOptionsFor(contentType, metadata)); + getGridFs().uploadFromStream(BsonUtils.simpleToBsonValue(upload.getFileId()), upload.getFilename(), + upload.getContent(), uploadOptions); + return upload.getFileId(); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java new file mode 100644 index 0000000000..ee80c7936e --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java @@ -0,0 +1,214 @@ +/* + * Copyright 2020 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 + * + * https://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.gridfs; + +import java.io.IOException; +import java.io.InputStream; + +import org.bson.Document; +import org.bson.types.ObjectId; +import org.springframework.data.util.Lazy; +import org.springframework.lang.Nullable; + +import com.mongodb.client.gridfs.model.GridFSFile; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +public class GridFsUpload implements GridFsObject { + + private static final InputStream EMPTY_STREAM = new InputStream() { + @Override + public int read() throws IOException { + return -1; + } + }; + + private ID id; + private Lazy dataStream; + private String filename; + private Options options; + + /** + * The {@link GridFSFile#getId()} value converted into its simple java type.
      + * A {@link org.bson.BsonString} will be converted to plain {@link String}. + * + * @return can be {@literal null}. + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFileId() + */ + @Override + public ID getFileId() { + return id; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFielname() + */ + @Override + public String getFilename() { + return filename; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getContent() + */ + @Override + public InputStream getContent() { + return dataStream.orElse(EMPTY_STREAM); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getOptions() + */ + @Override + public Options getOptions() { + return options; + } + + /** + * Create a new instance of {@link GridFsUpload} for the given {@link InputStream}. + * + * @param stream must not be {@literal null}. + * @return new instance of {@link GridFsUpload}. + */ + public static GridFsUploadBuilder fromStream(InputStream stream) { + return new GridFsUploadBuilder().content(stream); + } + + /** + * Builder to create {@link GridFsUpload} in a fluent way. + * + * @param the target id type. + */ + public static class GridFsUploadBuilder { + + private GridFsUpload upload; + + public GridFsUploadBuilder() { + this.upload = new GridFsUpload(); + this.upload.options = Options.none(); + } + + /** + * Define the content of the file to upload. + * + * @param stream the upload content. + * @return this. + */ + public GridFsUploadBuilder content(InputStream stream) { + + upload.dataStream = Lazy.of(() -> stream); + return this; + } + + /** + * Set the id to use. + * + * @param id the id to save the content to. + * @param + * @return this. + */ + public GridFsUploadBuilder id(T1 id) { + + upload.id = id; + return (GridFsUploadBuilder) this; + } + + /** + * Set the filename. + * + * @param filename the filename to use. + * @return this. + */ + public GridFsUploadBuilder filename(String filename) { + + upload.filename = filename; + return this; + } + + /** + * Set additional file information. + * + * @param options must not be {@literal null}. + * @return this. + */ + public GridFsUploadBuilder options(Options options) { + + upload.options = options; + return this; + } + + /** + * Set the file metadata. + * + * @param metadata must not be {@literal null}. + * @return + */ + public GridFsUploadBuilder metadata(Document metadata) { + + upload.options = upload.options.metadata(metadata); + return this; + } + + /** + * Set the upload chunk size in bytes. + * + * @param chunkSize use negative number for default. + * @return this. + */ + public GridFsUploadBuilder chunkSize(int chunkSize) { + + upload.options = upload.options.chunkSize(chunkSize); + return this; + } + + /** + * Set id, filename, metadata and chunk size from given file. + * + * @param gridFSFile must not be {@literal null}. + * @return this. + */ + public GridFsUploadBuilder gridFsFile(GridFSFile gridFSFile) { + + upload.id = gridFSFile.getId(); + upload.filename = gridFSFile.getFilename(); + upload.options = upload.options.metadata(gridFSFile.getMetadata()); + upload.options = upload.options.chunkSize(gridFSFile.getChunkSize()); + + return this; + } + + /** + * Set the content type. + * + * @param contentType must not be {@literal null}. + * @return this. + */ + public GridFsUploadBuilder contentType(String contentType) { + + upload.options = upload.options.contentType(contentType); + return this; + } + + public GridFsUpload build() { + return (GridFsUpload) upload; + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java index f189ea9d85..fa562582f1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java @@ -24,7 +24,10 @@ import org.springframework.core.io.buffer.DataBuffer; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.gridfs.ReactiveGridFsUpload.ReactiveGridFsUploadBuilder; import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; import com.mongodb.client.gridfs.model.GridFSFile; @@ -137,8 +140,36 @@ default Mono store(Publisher content, @Nullable String fil * @return a {@link Mono} emitting the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just * created. */ - Mono store(Publisher content, @Nullable String filename, @Nullable String contentType, - @Nullable Document metadata); + default Mono store(Publisher content, @Nullable String filename, @Nullable String contentType, + @Nullable Document metadata) { + + ReactiveGridFsUploadBuilder uploadBuilder = ReactiveGridFsUpload.fromPublisher(content); + + if (StringUtils.hasText(filename)) { + uploadBuilder.filename(filename); + } + if (StringUtils.hasText(contentType)) { + uploadBuilder.contentType(contentType); + } + if (!ObjectUtils.isEmpty(metadata)) { + uploadBuilder.metadata(metadata); + } + + return save(uploadBuilder.build()); + } + + /** + * Stores the given {@link GridFsObject}, likely a {@link GridFsUpload}, into into a file with given + * {@link GridFsObject#getFilename() name}. If the {@link GridFsObject#getFileId()} is set, the file will be stored + * with that id, otherwise the server auto creates a new id.
      + * + * @param upload the {@link GridFsObject} (most likely a {@link GridFsUpload}) to be stored. + * @param id type of the underlying {@link com.mongodb.client.gridfs.model.GridFSFile} + * @return {@link Mono} emitting the id of the stored file which is either an auto created value or + * {@link GridFsObject#getFileId()}. + * @since 3.0 + */ + Mono save(GridFsObject> upload); /** * Returns a {@link Flux} emitting all files matching the given query.
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java index ed71c4a3e5..411fc2a2d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java @@ -21,12 +21,14 @@ import java.io.InputStream; import java.util.concurrent.atomic.AtomicBoolean; +import org.bson.BsonValue; import org.reactivestreams.Publisher; import org.springframework.core.io.Resource; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -41,10 +43,12 @@ * @author Christoph Strobl * @since 2.2 */ -public class ReactiveGridFsResource { +public class ReactiveGridFsResource implements GridFsObject> { private final AtomicBoolean consumed = new AtomicBoolean(false); + private final @Nullable Object id; + private final Options options; private final String filename; private final @Nullable GridFSDownloadPublisher downloadPublisher; private final DataBufferFactory dataBufferFactory; @@ -56,21 +60,43 @@ public class ReactiveGridFsResource { * @param downloadPublisher */ public ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher downloadPublisher) { - this(filename, downloadPublisher, new DefaultDataBufferFactory()); + this(null, filename, Options.none(), downloadPublisher); } /** * Creates a new, absent {@link ReactiveGridFsResource}. * + * @param id * @param filename filename of the absent resource. + * @param options + * @param downloadPublisher + * @since 3.0 + */ + public ReactiveGridFsResource(@Nullable Object id, String filename, Options options, + @Nullable GridFSDownloadPublisher downloadPublisher) { + this(id, filename, options, downloadPublisher, new DefaultDataBufferFactory()); + } + + ReactiveGridFsResource(GridFSFile file, @Nullable GridFSDownloadPublisher downloadPublisher, DataBufferFactory dataBufferFactory) { + this(file.getId(), file.getFilename(), Options.from(file), downloadPublisher, dataBufferFactory); + } + + /** + * Creates a new, absent {@link ReactiveGridFsResource}. + * + * @param id + * @param filename filename of the absent resource. + * @param options * @param downloadPublisher * @param dataBufferFactory * @since 3.0 */ - ReactiveGridFsResource(String filename, @Nullable GridFSDownloadPublisher downloadPublisher, - DataBufferFactory dataBufferFactory) { + ReactiveGridFsResource(@Nullable Object id, String filename, Options options, + @Nullable GridFSDownloadPublisher downloadPublisher, DataBufferFactory dataBufferFactory) { + this.id = id; this.filename = filename; + this.options = options; this.downloadPublisher = downloadPublisher; this.dataBufferFactory = dataBufferFactory; } @@ -88,6 +114,15 @@ public static ReactiveGridFsResource absent(String filename) { return new ReactiveGridFsResource(filename, null); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFileId() + */ + @Override + public Object getFileId() { + return id instanceof BsonValue ? BsonUtils.toJavaType((BsonValue) id) : id; + } + /** * @see org.springframework.core.io.AbstractResource#getFilename() */ @@ -140,6 +175,24 @@ public Flux getDownloadStream() { return createDownloadStream(downloadPublisher); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getContent() + */ + @Override + public Flux getContent() { + return getDownloadStream(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getOptions() + */ + @Override + public Options getOptions() { + return options; + } + /** * Obtain the download stream emitting chunks of data with given {@code chunkSize} as they come in. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index f6867fb74b..49cd83fba0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -21,8 +21,6 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.nio.ByteBuffer; - import org.bson.Document; import org.bson.types.ObjectId; import org.reactivestreams.Publisher; @@ -34,6 +32,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.SerializationUtils; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -120,20 +119,29 @@ public Mono store(Publisher content, @Nullable String file /* * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#store(org.reactivestreams.Publisher, java.lang.String, java.lang.String, org.bson.Document) + * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#save(org.springframework.data.mongodb.gridfs.GridFsObject) */ - @Override - public Mono store(Publisher content, @Nullable String filename, @Nullable String contentType, - @Nullable Document metadata) { + public Mono save(GridFsObject> upload) { + + GridFSUploadOptions uploadOptions = computeUploadOptionsFor(upload.getOptions().getContentType(), + upload.getOptions().getMetadata()); - Assert.notNull(content, "Content must not be null!"); + if (upload.getOptions().getChunkSize() > 0) { + uploadOptions.chunkSizeBytes(upload.getOptions().getChunkSize()); + } + + if (upload.getFileId() == null) { + GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher(upload.getFilename(), + Flux.from(upload.getContent()).map(DataBuffer::asByteBuffer), uploadOptions); + + return (Mono) Mono.from(publisher); + } - GridFSUploadOptions uploadOptions = new GridFSUploadOptions(); - uploadOptions.metadata(metadata); + GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher( + BsonUtils.simpleToBsonValue(upload.getFileId()), upload.getFilename(), + Flux.from(upload.getContent()).map(DataBuffer::asByteBuffer), uploadOptions); - GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher(filename, - Flux.from(content).map(DataBuffer::asByteBuffer), uploadOptions); - return Mono.from(publisher); + return Mono.from(publisher).then(Mono.just(upload.getFileId())); } /* @@ -209,7 +217,7 @@ public Mono getResource(GridFSFile file) { Assert.notNull(file, "GridFSFile must not be null!"); return Mono.fromSupplier(() -> { - return new ReactiveGridFsResource(file.getFilename(), getGridFs().downloadToPublisher(file.getId()), dataBufferFactory); + return new ReactiveGridFsResource(file, getGridFs().downloadToPublisher(file.getId()), dataBufferFactory); }); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java new file mode 100644 index 0000000000..30a33f3ae0 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java @@ -0,0 +1,205 @@ +/* + * Copyright 2020 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 + * + * https://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.gridfs; + +import org.bson.Document; +import org.bson.types.ObjectId; +import org.reactivestreams.Publisher; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.lang.Nullable; + +import com.mongodb.client.gridfs.model.GridFSFile; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +public class ReactiveGridFsUpload implements GridFsObject> { + + private ID id; + private Publisher dataStream; + private String filename; + private Options options; + + /** + * The {@link GridFSFile#getId()} value converted into its simple java type.
      + * A {@link org.bson.BsonString} will be converted to plain {@link String}. + * + * @return can be {@literal null}. + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFileId() + */ + @Override + public ID getFileId() { + return id; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFielname() + */ + @Override + public String getFilename() { + return filename; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getContent() + */ + @Override + public Publisher getContent() { + return dataStream; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.gridfs.GridFsObject#getOptions() + */ + @Override + public Options getOptions() { + return options; + } + + /** + * Create a new instance of {@link ReactiveGridFsUpload} for the given {@link Publisher}. + * + * @param source must not be {@literal null}. + * @return new instance of {@link GridFsUpload}. + */ + public static ReactiveGridFsUploadBuilder fromPublisher(Publisher source) { + return new ReactiveGridFsUploadBuilder().content(source); + } + + /** + * Builder to create {@link ReactiveGridFsUpload} in a fluent way. + * + * @param the target id type. + */ + public static class ReactiveGridFsUploadBuilder { + + ReactiveGridFsUpload upload; + + public ReactiveGridFsUploadBuilder() { + + this.upload = new ReactiveGridFsUpload(); + this.upload.options = Options.none(); + } + + /** + * Define the content of the file to upload. + * + * @param source the upload content. + * @return this. + */ + public ReactiveGridFsUploadBuilder content(Publisher source) { + upload.dataStream = source; + return this; + } + + /** + * Set the id to use. + * + * @param id the id to save the content to. + * @param + * @return this. + */ + public ReactiveGridFsUploadBuilder id(T1 id) { + + upload.id = id; + return (ReactiveGridFsUploadBuilder) this; + } + + /** + * Set the filename. + * + * @param filename the filename to use. + * @return this. + */ + public ReactiveGridFsUploadBuilder filename(String filename) { + + upload.filename = filename; + return this; + } + + /** + * Set additional file information. + * + * @param options must not be {@literal null}. + * @return this. + */ + public ReactiveGridFsUploadBuilder options(Options options) { + + upload.options = options; + return this; + } + + /** + * Set the file metadata. + * + * @param metadata must not be {@literal null}. + * @return + */ + public ReactiveGridFsUploadBuilder metadata(Document metadata) { + + upload.options = upload.options.metadata(metadata); + return this; + } + + /** + * Set the upload chunk size in bytes. + * + * @param chunkSize use negative number for default. + * @return + */ + public ReactiveGridFsUploadBuilder chunkSize(int chunkSize) { + + upload.options = upload.options.chunkSize(chunkSize); + return this; + } + + /** + * Set id, filename, metadata and chunk size from given file. + * + * @param gridFSFile must not be {@literal null}. + * @return this. + */ + public ReactiveGridFsUploadBuilder gridFsFile(GridFSFile gridFSFile) { + + upload.id = gridFSFile.getId(); + upload.filename = gridFSFile.getFilename(); + upload.options = upload.options.metadata(gridFSFile.getMetadata()); + upload.options = upload.options.chunkSize(gridFSFile.getChunkSize()); + + return this; + } + + /** + * Set the content type. + * + * @param contentType must not be {@literal null}. + * @return this. + */ + public ReactiveGridFsUploadBuilder contentType(String contentType) { + + upload.options = upload.options.contentType(contentType); + return this; + } + + public ReactiveGridFsUpload build() { + return (ReactiveGridFsUpload) upload; + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index 7cd569ed47..e1e868da69 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -23,15 +23,24 @@ import java.util.function.Function; import java.util.stream.StreamSupport; +import org.bson.BsonBinary; +import org.bson.BsonBoolean; +import org.bson.BsonDouble; +import org.bson.BsonInt32; +import org.bson.BsonInt64; +import org.bson.BsonObjectId; +import org.bson.BsonString; import org.bson.BsonValue; import org.bson.Document; import org.bson.codecs.DocumentCodec; import org.bson.conversions.Bson; import org.bson.json.JsonParseException; +import org.bson.types.ObjectId; import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.CodecRegistryProvider; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.NumberUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -120,6 +129,60 @@ public static Object toJavaType(BsonValue value) { } } + /** + * Convert a given simple value (eg. {@link String}, {@link Long}) to its corresponding {@link BsonValue}. + * + * @param source must not be {@literal null}. + * @return the corresponding {@link BsonValue} representation. + * @throws IllegalArgumentException if {@literal source} does not correspond to a {@link BsonValue} type. + * @since 3.0 + */ + public static BsonValue simpleToBsonValue(Object source) { + + if (source instanceof BsonValue) { + return (BsonValue) source; + } + + if (source instanceof ObjectId) { + return new BsonObjectId((ObjectId) source); + } + + if (source instanceof String) { + return new BsonString((String) source); + } + + if (source instanceof Double) { + return new BsonDouble((Double) source); + } + + if (source instanceof Integer) { + return new BsonInt32((Integer) source); + } + + if (source instanceof Long) { + return new BsonInt64((Long) source); + } + + if (source instanceof byte[]) { + return new BsonBinary((byte[]) source); + } + + if (source instanceof Boolean) { + return new BsonBoolean((Boolean) source); + } + + if(source instanceof Float) { + return new BsonDouble((Float) source); + } + + if (source instanceof Double) { + return new BsonDouble((Double) source); + } + + throw new IllegalArgumentException( + String.format("Unable to convert % (%s) to BsonValue.", source, source != null ? source.getClass() : "null")); + } + /** * Merge the given {@link Document documents} into on in the given order. Keys contained within multiple documents are * overwritten by their follow ups. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index f3c99999f6..737f397f3e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -30,6 +30,7 @@ import java.util.stream.Stream; import org.bson.BsonObjectId; +import org.bson.BsonString; import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; @@ -289,6 +290,29 @@ public void getResourceShouldRetrieveContentByIdentity() throws IOException { } } + @Test // DATAMONGO-625 + public void storeSavesGridFsUploadWithGivenIdCorrectly() throws IOException { + + String id = "id-1"; + + GridFsUpload upload = GridFsUpload.fromStream(resource.getInputStream()) // + .id(id) // + .filename("gridFsUpload.xml") // + .contentType("xml") // + .build(); + + assertThat(operations.save(upload)).isEqualTo(id); + + GridFsResource fsFile = operations.getResource(operations.findOne(query(where("_id").is(id)))); + byte[] content = StreamUtils.copyToByteArray(fsFile.getInputStream()); + + assertThat(content).isEqualTo(StreamUtils.copyToByteArray(resource.getInputStream())); + assertThat(fsFile.getFilename()).isEqualTo("gridFsUpload.xml"); + assertThat(fsFile.getId()).isEqualTo(new BsonString(id)); + assertThat(fsFile.getFileId()).isEqualTo(id); + assertThat(fsFile.getContentType()).isEqualTo("xml"); + } + @Test // DATAMONGO-765 public void considersSkipLimitWhenQueryingFiles() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 1d0e3aff33..236f3b78d1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -29,12 +29,12 @@ import java.nio.ByteBuffer; import org.bson.BsonObjectId; +import org.bson.BsonString; import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -265,6 +265,41 @@ public void getResourcesByPattern() throws IOException { .verifyComplete(); } + @Test // DATAMONGO-625 + public void storeSavesGridFsUploadWithGivenIdCorrectly() throws IOException { + + String id = "id-1"; + byte[] content = StreamUtils.copyToByteArray(resource.getInputStream()); + Flux data = DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 256); + + ReactiveGridFsUpload upload = ReactiveGridFsUpload.fromPublisher(data) // + .id(id) // + .filename("gridFsUpload.xml") // + .contentType("xml") // + .build(); + + operations.save(upload).as(StepVerifier::create).expectNext(id).verifyComplete(); + + operations.findOne(query(where("_id").is(id))).flatMap(operations::getResource) + .flatMapMany(ReactiveGridFsResource::getDownloadStream) // + .transform(DataBufferUtils::join) // + .as(StepVerifier::create) // + .consumeNextWith(dataBuffer -> { + + byte[] actual = new byte[dataBuffer.readableByteCount()]; + dataBuffer.read(actual); + + assertThat(actual).isEqualTo(content); + }) // + .verifyComplete(); + + operations.findOne(query(where("_id").is(id))).as(StepVerifier::create).consumeNextWith(it -> { + assertThat(it.getFilename()).isEqualTo("gridFsUpload.xml"); + assertThat(it.getId()).isEqualTo(new BsonString(id)); + assertThat(it.getMetadata()).containsValue("xml"); + }).verifyComplete(); + } + @Test // DATAMONGO-765 public void considersSkipLimitWhenQueryingFiles() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java new file mode 100644 index 0000000000..9dd3755311 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2020 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 + * + * https://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.util.json; + +import static org.assertj.core.api.Assertions.*; + +import org.bson.BsonDouble; +import org.bson.BsonInt32; +import org.bson.BsonInt64; +import org.bson.BsonObjectId; +import org.bson.BsonString; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.util.BsonUtils; + +/** + * @author Christoph Strobl + */ +class BsonUtilsTest { + + @Test // DATAMONGO-625 + void simpleToBsonValue() { + + assertThat(BsonUtils.simpleToBsonValue(Long.valueOf(10))).isEqualTo(new BsonInt64(10)); + assertThat(BsonUtils.simpleToBsonValue(new Integer(10))).isEqualTo(new BsonInt32(10)); + assertThat(BsonUtils.simpleToBsonValue(Double.valueOf(0.1D))).isEqualTo(new BsonDouble(0.1D)); + assertThat(BsonUtils.simpleToBsonValue("value")).isEqualTo(new BsonString("value")); + } + + @Test // DATAMONGO-625 + void primitiveToBsonValue() { + assertThat(BsonUtils.simpleToBsonValue(10L)).isEqualTo(new BsonInt64(10)); + } + + @Test // DATAMONGO-625 + void objectIdToBsonValue() { + + ObjectId source = new ObjectId(); + assertThat(BsonUtils.simpleToBsonValue(source)).isEqualTo(new BsonObjectId(source)); + } + + @Test // DATAMONGO-625 + void bsonValueToBsonValue() { + + BsonObjectId source = new BsonObjectId(new ObjectId()); + assertThat(BsonUtils.simpleToBsonValue(source)).isSameAs(source); + } + + @Test // DATAMONGO-625 + void unsupportedToBsonValue() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> BsonUtils.simpleToBsonValue(new Object())); + } +} From 55fee27fb67389e3849417671d04857583905c01 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 20 Mar 2020 09:40:39 +0100 Subject: [PATCH 0125/1381] DATAMONGO-625 - Polishing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce default interface methods where possible. Rename save(…) to store(…) to align with method naming. Reduce constructor visibility to avoid invalid API usage. Replace mutable object in builder with fields to avoid mutation of already built objects when reusing the builder. Remove Options.chunked(…) factory method to avoid confusion with chunkSize method. Reformat code, strip trailing whitespaces. Original pull request: #842. --- .../data/mongodb/gridfs/GridFsObject.java | 29 ++---- .../data/mongodb/gridfs/GridFsOperations.java | 18 ++-- .../data/mongodb/gridfs/GridFsTemplate.java | 27 +---- .../data/mongodb/gridfs/GridFsUpload.java | 99 ++++++++++++------- .../gridfs/ReactiveGridFsOperations.java | 4 +- .../gridfs/ReactiveGridFsTemplate.java | 2 +- .../mongodb/gridfs/ReactiveGridFsUpload.java | 66 ++++++++----- .../data/mongodb/util/BsonUtils.java | 12 +-- .../GridFsTemplateIntegrationTests.java | 2 +- .../gridfs/ReactiveGridFsTemplateTests.java | 2 +- 10 files changed, 140 insertions(+), 121 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java index 592bab9409..fd158b82b4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java @@ -21,7 +21,7 @@ import com.mongodb.client.gridfs.model.GridFSFile; /** - * A common interface when dealing with GridFs items using Spring Data.o + * A common interface when dealing with GridFs items using Spring Data. * * @author Christoph Strobl * @since 3.0 @@ -31,7 +31,7 @@ public interface GridFsObject { /** * The {@link GridFSFile#getId()} value converted into its simple java type.
      * A {@link org.bson.BsonString} will be converted to plain {@link String}. - * + * * @return can be {@literal null} depending on the implementation. */ @Nullable @@ -39,34 +39,35 @@ public interface GridFsObject { /** * The filename. - * + * * @return */ String getFilename(); /** * The actual file content. - * + * * @return + * @throws IllegalStateException if the content cannot be obtained. */ CONTENT getContent(); /** * Additional information like file metadata (eg. contentType). - * + * * @return never {@literal null}. */ Options getOptions(); /** * Additional, context relevant information. - * + * * @author Christoph Strobl */ class Options { - private Document metadata = new Document(); - private int chunkSize = -1; + private final Document metadata; + private final int chunkSize; private Options(Document metadata, int chunkSize) { @@ -83,16 +84,6 @@ public static Options none() { return new Options(new Document(), -1); } - /** - * Static factory method to create {@link Options} with given chunk size. - * - * @param chunkSize - * @return new instance of {@link Options}. - */ - public static Options chunked(int chunkSize) { - return new Options(new Document(), chunkSize); - } - /** * Static factory method to create {@link Options} with given content type. * @@ -115,7 +106,7 @@ public static Options from(@Nullable GridFSFile gridFSFile) { /** * Set the associated content type. - * + * * @param contentType must not be {@literal null}. * @return new instance of {@link Options}. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index 5f7ee4ce91..0366668576 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -59,7 +59,9 @@ default ObjectId store(InputStream content, String filename) { * @param metadata can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, @Nullable Object metadata); + default ObjectId store(InputStream content, @Nullable Object metadata) { + return store(content, null, metadata); + } /** * Stores the given content into a file with the given name. @@ -80,7 +82,9 @@ default ObjectId store(InputStream content, @Nullable Document metadata) { * @param contentType can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType); + default ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType) { + return store(content, filename, contentType, null); + } /** * Stores the given content into a file with the given name using the given metadata. The metadata object will be @@ -91,7 +95,9 @@ default ObjectId store(InputStream content, @Nullable Document metadata) { * @param metadata can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ - ObjectId store(InputStream content, @Nullable String filename, @Nullable Object metadata); + default ObjectId store(InputStream content, @Nullable String filename, @Nullable Object metadata) { + return store(content, filename, null, metadata); + } /** * Stores the given content into a file with the given name and content type using the given metadata. The metadata @@ -141,21 +147,21 @@ default ObjectId store(InputStream content, @Nullable String filename, @Nullable uploadBuilder.metadata(metadata); } - return save(uploadBuilder.build()); + return store(uploadBuilder.build()); } /** * Stores the given {@link GridFsObject}, likely a {@link GridFsUpload}, into into a file with given * {@link GridFsObject#getFilename() name}. If the {@link GridFsObject#getFileId()} is set, the file will be stored * with that id, otherwise the server auto creates a new id.
      - * + * * @param upload the {@link GridFsObject} (most likely a {@link GridFsUpload}) to be stored. * @param id type of the underlying {@link com.mongodb.client.gridfs.model.GridFSFile} * @return the id of the stored file. Either an auto created value or {@link GridFsObject#getFileId()}, but never * {@literal null}. * @since 3.0 */ - T save(GridFsObject upload); + T store(GridFsObject upload); /** * Returns all files matching the given query. Note, that currently {@link Sort} criterias defined at the diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index cf8b2211c9..45702ef248 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -87,31 +87,6 @@ public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter, this.bucket = bucket; } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.Object) - */ - @Override - public ObjectId store(InputStream content, @Nullable Object metadata) { - return store(content, null, metadata); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String) - */ - public ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType) { - return store(content, filename, contentType, (Object) null); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.Object) - */ - public ObjectId store(InputStream content, @Nullable String filename, @Nullable Object metadata) { - return store(content, filename, null, metadata); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String, java.lang.Object) @@ -125,7 +100,7 @@ public ObjectId store(InputStream content, @Nullable String filename, @Nullable * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.GridFsOperations#save(org.springframework.data.mongodb.gridfs.GridFsObject) */ - public T save(GridFsObject upload) { + public T store(GridFsObject upload) { GridFSUploadOptions uploadOptions = computeUploadOptionsFor(upload.getOptions().getContentType(), upload.getOptions().getMetadata()); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java index ee80c7936e..c86926db77 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java @@ -15,42 +15,54 @@ */ package org.springframework.data.mongodb.gridfs; -import java.io.IOException; import java.io.InputStream; +import java.util.function.Supplier; import org.bson.Document; import org.bson.types.ObjectId; + import org.springframework.data.util.Lazy; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; import com.mongodb.client.gridfs.model.GridFSFile; /** + * Upload descriptor for a GridFS file upload. + * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ public class GridFsUpload implements GridFsObject { - private static final InputStream EMPTY_STREAM = new InputStream() { - @Override - public int read() throws IOException { - return -1; - } - }; + private final @Nullable ID id; + private final Lazy dataStream; + private final String filename; + private final Options options; - private ID id; - private Lazy dataStream; - private String filename; - private Options options; + private GridFsUpload(@Nullable ID id, Lazy dataStream, String filename, Options options) { + + Assert.notNull(dataStream, "Data Stream must not be null"); + Assert.notNull(filename, "Filename must not be null"); + Assert.notNull(options, "Options must not be null"); + + this.id = id; + this.dataStream = dataStream; + this.filename = filename; + this.options = options; + } /** * The {@link GridFSFile#getId()} value converted into its simple java type.
      * A {@link org.bson.BsonString} will be converted to plain {@link String}. - * + * * @return can be {@literal null}. * @see org.springframework.data.mongodb.gridfs.GridFsObject#getFileId() */ @Override + @Nullable public ID getFileId() { return id; } @@ -70,7 +82,7 @@ public String getFilename() { */ @Override public InputStream getContent() { - return dataStream.orElse(EMPTY_STREAM); + return dataStream.orElse(StreamUtils.emptyInput()); } /* @@ -89,22 +101,22 @@ public Options getOptions() { * @return new instance of {@link GridFsUpload}. */ public static GridFsUploadBuilder fromStream(InputStream stream) { - return new GridFsUploadBuilder().content(stream); + return new GridFsUploadBuilder().content(stream); } /** * Builder to create {@link GridFsUpload} in a fluent way. - * + * * @param the target id type. */ public static class GridFsUploadBuilder { - private GridFsUpload upload; + private Object id; + private Lazy dataStream; + private String filename; + private Options options = Options.none(); - public GridFsUploadBuilder() { - this.upload = new GridFsUpload(); - this.upload.options = Options.none(); - } + private GridFsUploadBuilder() {} /** * Define the content of the file to upload. @@ -114,7 +126,22 @@ public GridFsUploadBuilder() { */ public GridFsUploadBuilder content(InputStream stream) { - upload.dataStream = Lazy.of(() -> stream); + Assert.notNull(stream, "InputStream must not be null"); + + return content(() -> stream); + } + + /** + * Define the content of the file to upload. + * + * @param stream the upload content. + * @return this. + */ + public GridFsUploadBuilder content(Supplier stream) { + + Assert.notNull(stream, "InputStream Supplier must not be null"); + + this.dataStream = Lazy.of(stream); return this; } @@ -127,7 +154,7 @@ public GridFsUploadBuilder content(InputStream stream) { */ public GridFsUploadBuilder id(T1 id) { - upload.id = id; + this.id = id; return (GridFsUploadBuilder) this; } @@ -139,7 +166,7 @@ public GridFsUploadBuilder id(T1 id) { */ public GridFsUploadBuilder filename(String filename) { - upload.filename = filename; + this.filename = filename; return this; } @@ -151,7 +178,9 @@ public GridFsUploadBuilder filename(String filename) { */ public GridFsUploadBuilder options(Options options) { - upload.options = options; + Assert.notNull(options, "Options must not be null"); + + this.options = options; return this; } @@ -163,7 +192,7 @@ public GridFsUploadBuilder options(Options options) { */ public GridFsUploadBuilder metadata(Document metadata) { - upload.options = upload.options.metadata(metadata); + this.options = this.options.metadata(metadata); return this; } @@ -175,40 +204,42 @@ public GridFsUploadBuilder metadata(Document metadata) { */ public GridFsUploadBuilder chunkSize(int chunkSize) { - upload.options = upload.options.chunkSize(chunkSize); + this.options = this.options.chunkSize(chunkSize); return this; } /** * Set id, filename, metadata and chunk size from given file. - * + * * @param gridFSFile must not be {@literal null}. * @return this. */ public GridFsUploadBuilder gridFsFile(GridFSFile gridFSFile) { - upload.id = gridFSFile.getId(); - upload.filename = gridFSFile.getFilename(); - upload.options = upload.options.metadata(gridFSFile.getMetadata()); - upload.options = upload.options.chunkSize(gridFSFile.getChunkSize()); + Assert.notNull(gridFSFile, "GridFSFile must not be null"); + + this.id = gridFSFile.getId(); + this.filename = gridFSFile.getFilename(); + this.options = this.options.metadata(gridFSFile.getMetadata()); + this.options = this.options.chunkSize(gridFSFile.getChunkSize()); return this; } /** * Set the content type. - * + * * @param contentType must not be {@literal null}. * @return this. */ public GridFsUploadBuilder contentType(String contentType) { - upload.options = upload.options.contentType(contentType); + this.options = this.options.contentType(contentType); return this; } public GridFsUpload build() { - return (GridFsUpload) upload; + return new GridFsUpload(id, dataStream, filename, options); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java index fa562582f1..fe7f5bd145 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java @@ -155,7 +155,7 @@ default Mono store(Publisher content, @Nullable String fil uploadBuilder.metadata(metadata); } - return save(uploadBuilder.build()); + return store(uploadBuilder.build()); } /** @@ -169,7 +169,7 @@ default Mono store(Publisher content, @Nullable String fil * {@link GridFsObject#getFileId()}. * @since 3.0 */ - Mono save(GridFsObject> upload); + Mono store(GridFsObject> upload); /** * Returns a {@link Flux} emitting all files matching the given query.
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index 49cd83fba0..524de7b9b2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -121,7 +121,7 @@ public Mono store(Publisher content, @Nullable String file * (non-Javadoc) * @see org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations#save(org.springframework.data.mongodb.gridfs.GridFsObject) */ - public Mono save(GridFsObject> upload) { + public Mono store(GridFsObject> upload) { GridFSUploadOptions uploadOptions = computeUploadOptionsFor(upload.getOptions().getContentType(), upload.getOptions().getMetadata()); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java index 30a33f3ae0..9decedc78e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java @@ -20,19 +20,35 @@ import org.reactivestreams.Publisher; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import com.mongodb.client.gridfs.model.GridFSFile; /** + * Upload descriptor for a GridFS file upload. + * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0 */ public class ReactiveGridFsUpload implements GridFsObject> { - private ID id; - private Publisher dataStream; - private String filename; - private Options options; + private final @Nullable ID id; + private final Publisher dataStream; + private final String filename; + private final Options options; + + private ReactiveGridFsUpload(@Nullable ID id, Publisher dataStream, String filename, Options options) { + + Assert.notNull(dataStream, "Data Stream must not be null"); + Assert.notNull(filename, "Filename must not be null"); + Assert.notNull(options, "Options must not be null"); + + this.id = id; + this.dataStream = dataStream; + this.filename = filename; + this.options = options; + } /** * The {@link GridFSFile#getId()} value converted into its simple java type.
      @@ -42,6 +58,7 @@ public class ReactiveGridFsUpload implements GridFsObject fromPublisher(Publisher source) { - return new ReactiveGridFsUploadBuilder().content(source); + return new ReactiveGridFsUploadBuilder().content(source); } /** @@ -90,13 +107,12 @@ public static ReactiveGridFsUploadBuilder fromPublisher(Publisher { - ReactiveGridFsUpload upload; + private @Nullable Object id; + private Publisher dataStream; + private String filename; + private Options options = Options.none(); - public ReactiveGridFsUploadBuilder() { - - this.upload = new ReactiveGridFsUpload(); - this.upload.options = Options.none(); - } + private ReactiveGridFsUploadBuilder() {} /** * Define the content of the file to upload. @@ -105,7 +121,7 @@ public ReactiveGridFsUploadBuilder() { * @return this. */ public ReactiveGridFsUploadBuilder content(Publisher source) { - upload.dataStream = source; + this.dataStream = source; return this; } @@ -118,7 +134,7 @@ public ReactiveGridFsUploadBuilder content(Publisher source) { */ public ReactiveGridFsUploadBuilder id(T1 id) { - upload.id = id; + this.id = id; return (ReactiveGridFsUploadBuilder) this; } @@ -130,7 +146,7 @@ public ReactiveGridFsUploadBuilder id(T1 id) { */ public ReactiveGridFsUploadBuilder filename(String filename) { - upload.filename = filename; + this.filename = filename; return this; } @@ -142,7 +158,9 @@ public ReactiveGridFsUploadBuilder filename(String filename) { */ public ReactiveGridFsUploadBuilder options(Options options) { - upload.options = options; + Assert.notNull(options, "Options must not be null"); + + this.options = options; return this; } @@ -154,7 +172,7 @@ public ReactiveGridFsUploadBuilder options(Options options) { */ public ReactiveGridFsUploadBuilder metadata(Document metadata) { - upload.options = upload.options.metadata(metadata); + this.options = this.options.metadata(metadata); return this; } @@ -166,7 +184,7 @@ public ReactiveGridFsUploadBuilder metadata(Document metadata) { */ public ReactiveGridFsUploadBuilder chunkSize(int chunkSize) { - upload.options = upload.options.chunkSize(chunkSize); + this.options = this.options.chunkSize(chunkSize); return this; } @@ -178,10 +196,12 @@ public ReactiveGridFsUploadBuilder chunkSize(int chunkSize) { */ public ReactiveGridFsUploadBuilder gridFsFile(GridFSFile gridFSFile) { - upload.id = gridFSFile.getId(); - upload.filename = gridFSFile.getFilename(); - upload.options = upload.options.metadata(gridFSFile.getMetadata()); - upload.options = upload.options.chunkSize(gridFSFile.getChunkSize()); + Assert.notNull(gridFSFile, "GridFSFile must not be null"); + + this.id = gridFSFile.getId(); + this.filename = gridFSFile.getFilename(); + this.options = this.options.metadata(gridFSFile.getMetadata()); + this.options = this.options.chunkSize(gridFSFile.getChunkSize()); return this; } @@ -194,12 +214,12 @@ public ReactiveGridFsUploadBuilder gridFsFile(GridFSFile gridFSFile) { */ public ReactiveGridFsUploadBuilder contentType(String contentType) { - upload.options = upload.options.contentType(contentType); + this.options = this.options.contentType(contentType); return this; } public ReactiveGridFsUpload build() { - return (ReactiveGridFsUpload) upload; + return new ReactiveGridFsUpload(id, dataStream, filename, options); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index e1e868da69..c2dcec68bd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -36,11 +36,11 @@ import org.bson.conversions.Bson; import org.bson.json.JsonParseException; import org.bson.types.ObjectId; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.CodecRegistryProvider; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.util.NumberUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -171,16 +171,12 @@ public static BsonValue simpleToBsonValue(Object source) { return new BsonBoolean((Boolean) source); } - if(source instanceof Float) { + if (source instanceof Float) { return new BsonDouble((Float) source); } - if (source instanceof Double) { - return new BsonDouble((Double) source); - } - - throw new IllegalArgumentException( - String.format("Unable to convert % (%s) to BsonValue.", source, source != null ? source.getClass() : "null")); + throw new IllegalArgumentException(String.format("Unable to convert %s (%s) to BsonValue.", source, + source != null ? source.getClass().getName() : "null")); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 737f397f3e..ac012f4267 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -301,7 +301,7 @@ public void storeSavesGridFsUploadWithGivenIdCorrectly() throws IOException { .contentType("xml") // .build(); - assertThat(operations.save(upload)).isEqualTo(id); + assertThat(operations.store(upload)).isEqualTo(id); GridFsResource fsFile = operations.getResource(operations.findOne(query(where("_id").is(id)))); byte[] content = StreamUtils.copyToByteArray(fsFile.getInputStream()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 236f3b78d1..7ec42852c3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -278,7 +278,7 @@ public void storeSavesGridFsUploadWithGivenIdCorrectly() throws IOException { .contentType("xml") // .build(); - operations.save(upload).as(StepVerifier::create).expectNext(id).verifyComplete(); + operations.store(upload).as(StepVerifier::create).expectNext(id).verifyComplete(); operations.findOne(query(where("_id").is(id))).flatMap(operations::getResource) .flatMapMany(ReactiveGridFsResource::getDownloadStream) // From 0345eff69aad7f5bf43ece8f267b2f958ff5c858 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 30 Mar 2020 14:37:42 +0200 Subject: [PATCH 0126/1381] DATAMONGO-2477 - Polishing. Make sure that indexes get created where needed. --- .../PersonRepositoryIntegrationTests-context.xml | 7 +++++-- .../config/MongoNamespaceIntegrationTests-context.xml | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml index 05eba28ac5..264d474b56 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -8,9 +8,12 @@ http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> - + + + + @@ -29,5 +32,5 @@ - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml index f335c637f8..b70efb607c 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml @@ -11,8 +11,11 @@ + + + From d020219ded39237a28f11c39637ca5b6dbfebe71 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 31 Mar 2020 14:59:15 +0200 Subject: [PATCH 0127/1381] DATAMONGO-2492 - Updated changelog. --- src/main/resources/changelog.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 34ccdc2d98..91ba4637ad 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,23 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.RC1 (2020-03-31) +----------------------------------------- +* DATAMONGO-2501 - Upgrade to Querydsl 4.3. +* DATAMONGO-2498 - Upgrade to MongoDB 4.0.1 Drivers. +* DATAMONGO-2497 - Update documentation regarding @Transient properties usage in the persistence constructor. +* DATAMONGO-2492 - Release 3.0 RC1 (Neumann). +* DATAMONGO-2488 - KeyMapper.mapPropertyName does not work for nested arrays. +* DATAMONGO-2479 - More EntityCallback specializations. +* DATAMONGO-2477 - Disable auto-index creation by default. +* DATAMONGO-2475 - QueryDSL: $and and $or with more than two arguments in final query document. +* DATAMONGO-2416 - Add default methods accepting CriteriaDefinition on Fluent API. +* DATAMONGO-2300 - Can't read and convert DBRef when the type is Map. +* DATAMONGO-1026 - Joda, JSR-310 and ThreeTenBp converters are timezone-sensitive. +* DATAMONGO-931 - Add support for $redact operation. +* DATAMONGO-625 - GridFsOperations.createFile method should allow specification of _id. + + Changes in version 2.2.6.RELEASE (2020-03-25) --------------------------------------------- * DATAMONGO-2497 - Update documentation regarding @Transient properties usage in the persistence constructor. @@ -2960,3 +2977,4 @@ Repository + From dd336f0ecb033d45eb3065ee542327c895c83a0a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 31 Mar 2020 14:59:20 +0200 Subject: [PATCH 0128/1381] DATAMONGO-2492 - Prepare 3.0 RC1 (Neumann). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 78d003846a..2ab2705c43 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.RC1 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.RC1 4.0.1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index f1f11a2296..9462100533 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 M4 +Spring Data MongoDB 3.0 RC1 Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -12,3 +12,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 1e35116419d6e532863ea6489042f4312d74d049 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 31 Mar 2020 14:59:41 +0200 Subject: [PATCH 0129/1381] DATAMONGO-2492 - Release version 3.0 RC1 (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2ab2705c43..aa3d1b0a7b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC1 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..c84f39ece0 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC1 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..c277619c48 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC1 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 872db5d428..758f14565e 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC1 ../pom.xml From 90bd3f0f18be662de6c8023b583a8b0087ef1b64 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 31 Mar 2020 15:08:04 +0200 Subject: [PATCH 0130/1381] DATAMONGO-2492 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index aa3d1b0a7b..2ab2705c43 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC1 + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index c84f39ece0..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC1 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index c277619c48..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC1 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 758f14565e..872db5d428 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC1 + 3.0.0.BUILD-SNAPSHOT ../pom.xml From 4bbf4cd5cfc446848a0384eafa29f177d934f7b8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 31 Mar 2020 15:08:05 +0200 Subject: [PATCH 0131/1381] DATAMONGO-2492 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2ab2705c43..78d003846a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.RC1 + 2.3.0.BUILD-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.RC1 + 2.3.0.BUILD-SNAPSHOT 4.0.1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 28510de6c89d705f385b7903f1183435052977ad Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 3 Apr 2020 16:22:28 +0200 Subject: [PATCH 0132/1381] DATAMONGO-1677 - Adds a test to confirm a query with more than 10 arguments works just fine. Original Pull Request: #849 --- ...tractPersonRepositoryIntegrationTests.java | 20 ++++++++++++++++++- .../data/mongodb/repository/Address.java | 6 +++--- .../mongodb/repository/PersonRepository.java | 6 ++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 2a9f98d1b9..d92b6dbf41 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -36,7 +36,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.IncorrectResultSizeDataAccessException; @@ -1338,4 +1337,23 @@ public void findsWithNativeProjection() { assertThat(repository.findDocumentById(dave.getId()).get()).containsEntry("firstname", dave.getFirstname()) .containsEntry("lastname", dave.getLastname()); } + + @Test // DATAMONGO-1677 + public void findWithMoreThan10Arguments() { + + alicia.setSkills(Arrays.asList("musician", "singer", "composer", "actress", "pianist")); + alicia.setAddress(new Address("street", "zipCode", "city")); + alicia.setUniqueId(UUID.randomUUID()); + UsernameAndPassword credentials = new UsernameAndPassword(); + credentials.password = "keys"; + credentials.username = "alicia"; + alicia.credentials = credentials; + + alicia = repository.save(this.alicia); + + assertThat(repository.findPersonByManyArguments(this.alicia.getFirstname(), this.alicia.getLastname(), this.alicia.getEmail(), + this.alicia.getAge(), Sex.FEMALE, this.alicia.createdAt, alicia.getSkills(), "street", "zipCode", "city", + alicia.getUniqueId(), credentials.username, credentials.password) + ).isNotNull(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java index 45defa38a6..281c4bcfeb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Address.java @@ -32,9 +32,9 @@ protected Address() { } /** - * @param string - * @param string2 - * @param string3 + * @param street + * @param zipcode + * @param city */ public Address(String street, String zipcode, String city) { this.street = street; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index b65bd3d8ce..b2e8f6f86d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -394,4 +394,10 @@ Page findByCustomQueryLastnameAndAddressStreetInList(String lastname, Li @Query(value = "{_id:?0}") Optional findDocumentById(String id); + + @Query( + value = "{ 'firstname' : ?0, 'lastname' : ?1, 'email' : ?2 , 'age' : ?3, 'sex' : ?4, 'createdAt' : ?5, 'skills' : ?6, 'address.street' : ?7, 'address.zipCode' : ?8, 'address.city' : ?9, 'uniqueId' : ?10, 'credentials.username' : ?11, 'credentials.password' : ?12 }") + Person findPersonByManyArguments(String firstname, String lastname, String email, Integer age, Sex sex, + Date createdAt, List skills, String street, String zipCode, String city, UUID uniqueId, String username, + String password); } From 5dd91d0b6ddbc2cd6d28a2f2754cef020f77b37f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 6 Apr 2020 08:28:17 +0200 Subject: [PATCH 0133/1381] DATAMONGO-1677 - Polishing. Switch tests to JUnit Jupiter. Original Pull Request: #849 --- ...tractPersonRepositoryIntegrationTests.java | 272 +++++++++--------- .../mongodb/repository/PersonRepository.java | 9 +- .../RedeclaringRepositoryMethodsTests.java | 9 +- .../MongoNamespaceIntegrationTests.java | 13 +- 4 files changed, 151 insertions(+), 152 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index d92b6dbf41..cd41e8ffa5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -32,10 +32,11 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.assertj.core.api.Assertions; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.IncorrectResultSizeDataAccessException; @@ -63,7 +64,7 @@ import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.mongodb.repository.SampleEvaluationContextExtension.SampleSecurityContextHolder; import org.springframework.data.querydsl.QSort; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.util.ReflectionTestUtils; /** @@ -76,7 +77,7 @@ * @author Fırat KÜÇÜK * @author Edward Prentice */ -@RunWith(SpringRunner.class) +@ExtendWith(SpringExtension.class) public abstract class AbstractPersonRepositoryIntegrationTests { @Autowired protected PersonRepository repository; @@ -88,7 +89,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { List all; - @Before + @BeforeEach public void setUp() throws InterruptedException { repository.deleteAll(); @@ -116,26 +117,26 @@ public void setUp() throws InterruptedException { } @Test - public void findsPersonById() { + void findsPersonById() { assertThat(repository.findById(dave.getId())).contains(dave); } @Test - public void findsAllMusicians() { + void findsAllMusicians() { List result = repository.findAll(); assertThat(result).hasSameSizeAs(all).containsAll(all); } @Test - public void findsAllWithGivenIds() { + void findsAllWithGivenIds() { Iterable result = repository.findAllById(asList(dave.id, boyd.id)); assertThat(result).contains(dave, boyd).doesNotContain(oliver, carter, stefan, leroi, alicia); } @Test - public void deletesPersonCorrectly() { + void deletesPersonCorrectly() { repository.delete(dave); @@ -145,7 +146,7 @@ public void deletesPersonCorrectly() { } @Test - public void deletesPersonByIdCorrectly() { + void deletesPersonByIdCorrectly() { repository.deleteById(dave.getId()); @@ -155,14 +156,14 @@ public void deletesPersonByIdCorrectly() { } @Test - public void findsPersonsByLastname() { + void findsPersonsByLastname() { List result = repository.findByLastname("Beauford"); assertThat(result).hasSize(1).contains(carter); } @Test - public void findsPersonsByFirstname() { + void findsPersonsByFirstname() { List result = repository.findByThePersonsFirstname("Leroi"); assertThat(result).hasSize(1).contains(leroi); @@ -170,20 +171,20 @@ public void findsPersonsByFirstname() { } @Test - public void findsPersonsByFirstnameLike() { + void findsPersonsByFirstnameLike() { List result = repository.findByFirstnameLike("Bo*"); assertThat(result).hasSize(1).contains(boyd); } @Test // DATAMONGO-1608 - public void findByFirstnameLikeWithNull() { + void findByFirstnameLikeWithNull() { assertThatIllegalArgumentException().isThrownBy(() -> repository.findByFirstnameLike(null)); } @Test - public void findsPagedPersons() { + void findsPagedPersons() { Page result = repository.findAll(PageRequest.of(1, 2, Direction.ASC, "lastname", "firstname")); assertThat(result.isFirst()).isFalse(); @@ -192,7 +193,7 @@ public void findsPagedPersons() { } @Test - public void executesPagedFinderCorrectly() { + void executesPagedFinderCorrectly() { Page page = repository.findByLastnameLike("*a*", PageRequest.of(0, 2, Direction.ASC, "lastname", "firstname")); @@ -203,7 +204,7 @@ public void executesPagedFinderCorrectly() { } @Test - public void executesPagedFinderWithAnnotatedQueryCorrectly() { + void executesPagedFinderWithAnnotatedQueryCorrectly() { Page page = repository.findByLastnameLikeWithPageable(".*a.*", PageRequest.of(0, 2, Direction.ASC, "lastname", "firstname")); @@ -214,14 +215,14 @@ public void executesPagedFinderWithAnnotatedQueryCorrectly() { } @Test - public void findsPersonInAgeRangeCorrectly() { + void findsPersonInAgeRangeCorrectly() { List result = repository.findByAgeBetween(40, 45); assertThat(result).hasSize(2).contains(dave, leroi); } @Test - public void findsPersonByShippingAddressesCorrectly() { + void findsPersonByShippingAddressesCorrectly() { Address address = new Address("Foo Street 1", "C0123", "Bar"); dave.setShippingAddresses(new HashSet
      (asList(address))); @@ -231,7 +232,7 @@ public void findsPersonByShippingAddressesCorrectly() { } @Test - public void findsPersonByAddressCorrectly() { + void findsPersonByAddressCorrectly() { Address address = new Address("Foo Street 1", "C0123", "Bar"); dave.setAddress(address); @@ -242,7 +243,7 @@ public void findsPersonByAddressCorrectly() { } @Test - public void findsPeopleByZipCode() { + void findsPeopleByZipCode() { Address address = new Address("Foo Street 1", "C0123", "Bar"); dave.setAddress(address); @@ -253,14 +254,14 @@ public void findsPeopleByZipCode() { } @Test - public void findsPeopleByQueryDslLastnameSpec() { + void findsPeopleByQueryDslLastnameSpec() { Iterable result = repository.findAll(person.lastname.eq("Matthews")); assertThat(result).contains(dave).doesNotContain(carter, boyd, stefan, leroi, alicia); } @Test - public void findsPeopleByzipCodePredicate() { + void findsPeopleByzipCodePredicate() { Address address = new Address("Foo Street 1", "C0123", "Bar"); dave.setAddress(address); @@ -271,7 +272,7 @@ public void findsPeopleByzipCodePredicate() { } @Test - public void findsPeopleByLocationNear() { + void findsPeopleByLocationNear() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); repository.save(dave); @@ -281,7 +282,7 @@ public void findsPeopleByLocationNear() { } @Test // DATAMONGO-1588 - public void findsPeopleByLocationNearUsingGeoJsonType() { + void findsPeopleByLocationNearUsingGeoJsonType() { GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); dave.setLocation(point); @@ -292,7 +293,7 @@ public void findsPeopleByLocationNearUsingGeoJsonType() { } @Test - public void findsPeopleByLocationWithinCircle() { + void findsPeopleByLocationWithinCircle() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); repository.save(dave); @@ -302,7 +303,7 @@ public void findsPeopleByLocationWithinCircle() { } @Test - public void findsPeopleByLocationWithinBox() { + void findsPeopleByLocationWithinBox() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); repository.save(dave); @@ -314,7 +315,7 @@ public void findsPeopleByLocationWithinBox() { } @Test - public void findsPeopleByLocationWithinPolygon() { + void findsPeopleByLocationWithinPolygon() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -330,7 +331,7 @@ public void findsPeopleByLocationWithinPolygon() { } @Test - public void findsPagedPeopleByPredicate() { + void findsPagedPeopleByPredicate() { Page page = repository.findAll(person.lastname.contains("a"), PageRequest.of(0, 2, Direction.ASC, "lastname")); @@ -342,7 +343,7 @@ public void findsPagedPeopleByPredicate() { } @Test // DATADOC-136 - public void findsPeopleBySexCorrectly() { + void findsPeopleBySexCorrectly() { List females = repository.findBySex(Sex.FEMALE); assertThat(females).hasSize(1); @@ -350,36 +351,36 @@ public void findsPeopleBySexCorrectly() { } @Test // DATAMONGO-446 - public void findsPeopleBySexPaginated() { + void findsPeopleBySexPaginated() { List males = repository.findBySex(Sex.MALE, PageRequest.of(0, 2)); assertThat(males).hasSize(2); } @Test - public void findsPeopleByNamedQuery() { + void findsPeopleByNamedQuery() { List result = repository.findByNamedQuery("Dave"); assertThat(result).hasSize(1).contains(dave); } @Test // DATADOC-190 - public void existsWorksCorrectly() { + void existsWorksCorrectly() { assertThat(repository.existsById(dave.getId())).isTrue(); } - @Test(expected = DuplicateKeyException.class) - public void rejectsDuplicateEmailAddressOnSave() { + @Test + void rejectsDuplicateEmailAddressOnSave() { assertThat(dave.getEmail()).isEqualTo("dave@dmband.com"); Person daveSyer = new Person("Dave", "Syer"); assertThat(daveSyer.getEmail()).isEqualTo("dave@dmband.com"); - repository.save(daveSyer); + Assertions.assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(() -> repository.save(daveSyer)); } @Test // DATADOC-236 - public void findsPeopleByLastnameAndOrdersCorrectly() { + void findsPeopleByLastnameAndOrdersCorrectly() { List result = repository.findByLastnameOrderByFirstnameAsc("Matthews"); assertThat(result).hasSize(2); assertThat(result.get(0)).isEqualTo(dave); @@ -387,7 +388,7 @@ public void findsPeopleByLastnameAndOrdersCorrectly() { } @Test // DATADOC-236 - public void appliesStaticAndDynamicSorting() { + void appliesStaticAndDynamicSorting() { List result = repository.findByFirstnameLikeOrderByLastnameAsc("*e*", Sort.by("age")); assertThat(result).hasSize(5); assertThat(result.get(0)).isEqualTo(carter); @@ -398,7 +399,7 @@ public void appliesStaticAndDynamicSorting() { } @Test - public void executesGeoNearQueryForResultsCorrectly() { + void executesGeoNearQueryForResultsCorrectly() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -410,7 +411,7 @@ public void executesGeoNearQueryForResultsCorrectly() { } @Test - public void executesGeoPageQueryForResultsCorrectly() { + void executesGeoPageQueryForResultsCorrectly() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -425,7 +426,7 @@ public void executesGeoPageQueryForResultsCorrectly() { } @Test // DATAMONGO-323 - public void considersSortForAnnotatedQuery() { + void considersSortForAnnotatedQuery() { List result = repository.findByAgeLessThan(60, Sort.by("firstname")); @@ -440,7 +441,7 @@ public void considersSortForAnnotatedQuery() { } @Test // DATAMONGO-347 - public void executesQueryWithDBRefReferenceCorrectly() { + void executesQueryWithDBRefReferenceCorrectly() { operations.remove(new Query(), User.class); @@ -457,49 +458,49 @@ public void executesQueryWithDBRefReferenceCorrectly() { } @Test // DATAMONGO-425 - public void bindsDateParameterForLessThanPredicateCorrectly() { + void bindsDateParameterForLessThanPredicateCorrectly() { List result = repository.findByCreatedAtLessThan(boyd.createdAt); assertThat(result).hasSize(3).contains(dave, oliver, carter); } @Test // DATAMONGO-425 - public void bindsDateParameterForGreaterThanPredicateCorrectly() { + void bindsDateParameterForGreaterThanPredicateCorrectly() { List result = repository.findByCreatedAtGreaterThan(carter.createdAt); assertThat(result).hasSize(4).contains(boyd, stefan, leroi, alicia); } @Test // DATAMONGO-427 - public void bindsDateParameterToBeforePredicateCorrectly() { + void bindsDateParameterToBeforePredicateCorrectly() { List result = repository.findByCreatedAtBefore(boyd.createdAt); assertThat(result).hasSize(3).contains(dave, oliver, carter); } @Test // DATAMONGO-427 - public void bindsDateParameterForAfterPredicateCorrectly() { + void bindsDateParameterForAfterPredicateCorrectly() { List result = repository.findByCreatedAtAfter(carter.createdAt); assertThat(result).hasSize(4).contains(boyd, stefan, leroi, alicia); } @Test // DATAMONGO-425 - public void bindsDateParameterForManuallyDefinedQueryCorrectly() { + void bindsDateParameterForManuallyDefinedQueryCorrectly() { List result = repository.findByCreatedAtLessThanManually(boyd.createdAt); assertThat(result).isNotEmpty(); } @Test // DATAMONGO-472 - public void findsPeopleUsingNotPredicate() { + void findsPeopleUsingNotPredicate() { List result = repository.findByLastnameNot("Matthews"); assertThat(result).doesNotContain(dave).hasSize(5); } @Test // DATAMONGO-521 - public void executesAndQueryCorrectly() { + void executesAndQueryCorrectly() { List result = repository.findByFirstnameAndLastname("Dave", "Matthews"); @@ -511,7 +512,7 @@ public void executesAndQueryCorrectly() { } @Test // DATAMONGO-600 - public void readsDocumentsWithNestedPolymorphismCorrectly() { + void readsDocumentsWithNestedPolymorphismCorrectly() { UsernameAndPassword usernameAndPassword = new UsernameAndPassword(); usernameAndPassword.username = "dave"; @@ -526,48 +527,48 @@ public void readsDocumentsWithNestedPolymorphismCorrectly() { } @Test // DATAMONGO-636 - public void executesDerivedCountProjection() { + void executesDerivedCountProjection() { assertThat(repository.countByLastname("Matthews")).isEqualTo(2L); } @Test // DATAMONGO-636 - public void executesDerivedCountProjectionToInt() { + void executesDerivedCountProjectionToInt() { assertThat(repository.countByFirstname("Oliver August")).isEqualTo(1); } @Test // DATAMONGO-636 - public void executesAnnotatedCountProjection() { + void executesAnnotatedCountProjection() { assertThat(repository.someCountQuery("Matthews")).isEqualTo(2L); } @Test // DATAMONGO-1454 - public void executesDerivedExistsProjectionToBoolean() { + void executesDerivedExistsProjectionToBoolean() { assertThat(repository.existsByFirstname("Oliver August")).isTrue(); assertThat(repository.existsByFirstname("Hans Peter")).isFalse(); } @Test // DATAMONGO-1454 - public void executesAnnotatedExistProjection() { + void executesAnnotatedExistProjection() { assertThat(repository.someExistQuery("Matthews")).isTrue(); } @Test // DATAMONGO-701 - public void executesDerivedStartsWithQueryCorrectly() { + void executesDerivedStartsWithQueryCorrectly() { List result = repository.findByLastnameStartsWith("Matt"); assertThat(result).hasSize(2).contains(dave, oliver); } @Test // DATAMONGO-701 - public void executesDerivedEndsWithQueryCorrectly() { + void executesDerivedEndsWithQueryCorrectly() { List result = repository.findByLastnameEndsWith("thews"); assertThat(result).hasSize(2).contains(dave, oliver); } @Test // DATAMONGO-445 - public void executesGeoPageQueryForWithPageRequestForPageInBetween() { + void executesGeoPageQueryForWithPageRequestForPageInBetween() { Point farAway = new Point(-73.9, 40.7); Point here = new Point(-73.99, 40.73); @@ -592,7 +593,7 @@ public void executesGeoPageQueryForWithPageRequestForPageInBetween() { } @Test // DATAMONGO-445 - public void executesGeoPageQueryForWithPageRequestForPageAtTheEnd() { + void executesGeoPageQueryForWithPageRequestForPageAtTheEnd() { Point point = new Point(-73.99171, 40.738868); @@ -612,7 +613,7 @@ public void executesGeoPageQueryForWithPageRequestForPageAtTheEnd() { } @Test // DATAMONGO-445 - public void executesGeoPageQueryForWithPageRequestForJustOneElement() { + void executesGeoPageQueryForWithPageRequestForJustOneElement() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -629,7 +630,7 @@ public void executesGeoPageQueryForWithPageRequestForJustOneElement() { } @Test // DATAMONGO-445 - public void executesGeoPageQueryForWithPageRequestForJustOneElementEmptyPage() { + void executesGeoPageQueryForWithPageRequestForJustOneElementEmptyPage() { dave.setLocation(new Point(-73.99171, 40.738868)); repository.save(dave); @@ -645,13 +646,13 @@ public void executesGeoPageQueryForWithPageRequestForJustOneElementEmptyPage() { } @Test // DATAMONGO-1608 - public void findByFirstNameIgnoreCaseWithNull() { + void findByFirstNameIgnoreCaseWithNull() { assertThatIllegalArgumentException().isThrownBy(() -> repository.findByFirstnameIgnoreCase(null)); } @Test // DATAMONGO-770 - public void findByFirstNameIgnoreCase() { + void findByFirstNameIgnoreCase() { List result = repository.findByFirstnameIgnoreCase("dave"); @@ -660,7 +661,7 @@ public void findByFirstNameIgnoreCase() { } @Test // DATAMONGO-770 - public void findByFirstnameNotIgnoreCase() { + void findByFirstnameNotIgnoreCase() { List result = repository.findByFirstnameNotIgnoreCase("dave"); @@ -668,7 +669,7 @@ public void findByFirstnameNotIgnoreCase() { } @Test // DATAMONGO-770 - public void findByFirstnameStartingWithIgnoreCase() { + void findByFirstnameStartingWithIgnoreCase() { List result = repository.findByFirstnameStartingWithIgnoreCase("da"); assertThat(result).hasSize(1); @@ -676,7 +677,7 @@ public void findByFirstnameStartingWithIgnoreCase() { } @Test // DATAMONGO-770 - public void findByFirstnameEndingWithIgnoreCase() { + void findByFirstnameEndingWithIgnoreCase() { List result = repository.findByFirstnameEndingWithIgnoreCase("VE"); assertThat(result).hasSize(1); @@ -684,7 +685,7 @@ public void findByFirstnameEndingWithIgnoreCase() { } @Test // DATAMONGO-770 - public void findByFirstnameContainingIgnoreCase() { + void findByFirstnameContainingIgnoreCase() { List result = repository.findByFirstnameContainingIgnoreCase("AV"); assertThat(result).hasSize(1); @@ -692,7 +693,7 @@ public void findByFirstnameContainingIgnoreCase() { } @Test // DATAMONGO-870 - public void findsSliceOfPersons() { + void findsSliceOfPersons() { Slice result = repository.findByAgeGreaterThan(40, PageRequest.of(0, 2, Direction.DESC, "firstname")); @@ -700,7 +701,7 @@ public void findsSliceOfPersons() { } @Test // DATAMONGO-871 - public void findsPersonsByFirstnameAsArray() { + void findsPersonsByFirstnameAsArray() { Person[] result = repository.findByThePersonsFirstnameAsArray("Leroi"); @@ -708,7 +709,7 @@ public void findsPersonsByFirstnameAsArray() { } @Test // DATAMONGO-821 - public void findUsingAnnotatedQueryOnDBRef() { + void findUsingAnnotatedQueryOnDBRef() { operations.remove(new org.springframework.data.mongodb.core.query.Query(), User.class); @@ -726,7 +727,7 @@ public void findUsingAnnotatedQueryOnDBRef() { } @Test // DATAMONGO-566 - public void deleteByShouldReturnListOfDeletedElementsWhenRetunTypeIsCollectionLike() { + void deleteByShouldReturnListOfDeletedElementsWhenRetunTypeIsCollectionLike() { List result = repository.deleteByLastname("Beauford"); @@ -734,7 +735,7 @@ public void deleteByShouldReturnListOfDeletedElementsWhenRetunTypeIsCollectionLi } @Test // DATAMONGO-566 - public void deleteByShouldRemoveElementsMatchingDerivedQuery() { + void deleteByShouldRemoveElementsMatchingDerivedQuery() { repository.deleteByLastname("Beauford"); @@ -742,29 +743,29 @@ public void deleteByShouldRemoveElementsMatchingDerivedQuery() { } @Test // DATAMONGO-566 - public void deleteByShouldReturnNumberOfDocumentsRemovedIfReturnTypeIsLong() { + void deleteByShouldReturnNumberOfDocumentsRemovedIfReturnTypeIsLong() { assertThat(repository.deletePersonByLastname("Beauford")).isEqualTo(1L); } @Test // DATAMONGO-1997 - public void deleteByShouldResultWrappedInOptionalCorrectly() { + void deleteByShouldResultWrappedInOptionalCorrectly() { assertThat(repository.deleteOptionalByLastname("Beauford")).isPresent(); assertThat(repository.deleteOptionalByLastname("dorfuaeB")).isNotPresent(); } @Test // DATAMONGO-566 - public void deleteByShouldReturnZeroInCaseNoDocumentHasBeenRemovedAndReturnTypeIsNumber() { + void deleteByShouldReturnZeroInCaseNoDocumentHasBeenRemovedAndReturnTypeIsNumber() { assertThat(repository.deletePersonByLastname("dorfuaeB")).isEqualTo(0L); } @Test // DATAMONGO-566 - public void deleteByShouldReturnEmptyListInCaseNoDocumentHasBeenRemovedAndReturnTypeIsCollectionLike() { + void deleteByShouldReturnEmptyListInCaseNoDocumentHasBeenRemovedAndReturnTypeIsCollectionLike() { assertThat(repository.deleteByLastname("dorfuaeB")).isEmpty(); } @Test // DATAMONGO-566 - public void deleteByUsingAnnotatedQueryShouldReturnListOfDeletedElementsWhenRetunTypeIsCollectionLike() { + void deleteByUsingAnnotatedQueryShouldReturnListOfDeletedElementsWhenRetunTypeIsCollectionLike() { List result = repository.removeByLastnameUsingAnnotatedQuery("Beauford"); @@ -772,7 +773,7 @@ public void deleteByUsingAnnotatedQueryShouldReturnListOfDeletedElementsWhenRetu } @Test // DATAMONGO-566 - public void deleteByUsingAnnotatedQueryShouldRemoveElementsMatchingDerivedQuery() { + void deleteByUsingAnnotatedQueryShouldRemoveElementsMatchingDerivedQuery() { repository.removeByLastnameUsingAnnotatedQuery("Beauford"); @@ -780,12 +781,12 @@ public void deleteByUsingAnnotatedQueryShouldRemoveElementsMatchingDerivedQuery( } @Test // DATAMONGO-566 - public void deleteByUsingAnnotatedQueryShouldReturnNumberOfDocumentsRemovedIfReturnTypeIsLong() { + void deleteByUsingAnnotatedQueryShouldReturnNumberOfDocumentsRemovedIfReturnTypeIsLong() { assertThat(repository.removePersonByLastnameUsingAnnotatedQuery("Beauford")).isEqualTo(1L); } @Test // DATAMONGO-893 - public void findByNestedPropertyInCollectionShouldFindMatchingDocuments() { + void findByNestedPropertyInCollectionShouldFindMatchingDocuments() { Person p = new Person("Mary", "Poppins"); Address adr = new Address("some", "2", "where"); @@ -799,7 +800,7 @@ public void findByNestedPropertyInCollectionShouldFindMatchingDocuments() { } @Test // DATAMONGO-745 - public void findByCustomQueryFirstnamesInListAndLastname() { + void findByCustomQueryFirstnamesInListAndLastname() { repository.save(new Person("foo", "bar")); repository.save(new Person("bar", "bar")); @@ -815,7 +816,7 @@ public void findByCustomQueryFirstnamesInListAndLastname() { } @Test // DATAMONGO-745 - public void findByCustomQueryLastnameAndStreetInList() { + void findByCustomQueryLastnameAndStreetInList() { repository.save(new Person("foo", "bar").withAddress(new Address("street1", "1", "SB"))); repository.save(new Person("bar", "bar").withAddress(new Address("street2", "1", "SB"))); @@ -832,7 +833,7 @@ public void findByCustomQueryLastnameAndStreetInList() { } @Test // DATAMONGO-950 - public void shouldLimitCollectionQueryToMaxResultsWhenPresent() { + void shouldLimitCollectionQueryToMaxResultsWhenPresent() { repository.saveAll(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan"))); @@ -841,7 +842,7 @@ public void shouldLimitCollectionQueryToMaxResultsWhenPresent() { } @Test // DATAMONGO-950, DATAMONGO-1464 - public void shouldNotLimitPagedQueryWhenPageRequestWithinBounds() { + void shouldNotLimitPagedQueryWhenPageRequestWithinBounds() { repository.saveAll(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan"))); @@ -851,7 +852,7 @@ public void shouldNotLimitPagedQueryWhenPageRequestWithinBounds() { } @Test // DATAMONGO-950 - public void shouldLimitPagedQueryWhenPageRequestExceedsUpperBoundary() { + void shouldLimitPagedQueryWhenPageRequestExceedsUpperBoundary() { repository.saveAll(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan"))); @@ -860,7 +861,7 @@ public void shouldLimitPagedQueryWhenPageRequestExceedsUpperBoundary() { } @Test // DATAMONGO-950, DATAMONGO-1464 - public void shouldReturnEmptyWhenPageRequestedPageIsTotallyOutOfScopeForLimit() { + void shouldReturnEmptyWhenPageRequestedPageIsTotallyOutOfScopeForLimit() { repository.saveAll(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan"))); @@ -870,7 +871,7 @@ public void shouldReturnEmptyWhenPageRequestedPageIsTotallyOutOfScopeForLimit() } @Test // DATAMONGO-996, DATAMONGO-950, DATAMONGO-1464 - public void gettingNonFirstPageWorksWithoutLimitBeingSet() { + void gettingNonFirstPageWorksWithoutLimitBeingSet() { Page slice = repository.findByLastnameLike("Matthews", PageRequest.of(1, 1)); @@ -881,7 +882,7 @@ public void gettingNonFirstPageWorksWithoutLimitBeingSet() { } @Test // DATAMONGO-972 - public void shouldExecuteFindOnDbRefCorrectly() { + void shouldExecuteFindOnDbRefCorrectly() { operations.remove(new org.springframework.data.mongodb.core.query.Query(), User.class); @@ -897,12 +898,12 @@ public void shouldExecuteFindOnDbRefCorrectly() { } @Test // DATAMONGO-969 - public void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { + void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { assertThat(repository.findAll(person.id.in(Arrays.asList(dave.id, carter.id)))).contains(dave, carter); } @Test // DATAMONGO-1030 - public void executesSingleEntityQueryWithProjectionCorrectly() { + void executesSingleEntityQueryWithProjectionCorrectly() { PersonSummaryDto result = repository.findSummaryByLastname("Beauford"); @@ -912,7 +913,7 @@ public void executesSingleEntityQueryWithProjectionCorrectly() { } @Test // DATAMONGO-1057 - public void sliceShouldTraverseElementsWithoutSkippingOnes() { + void sliceShouldTraverseElementsWithoutSkippingOnes() { repository.deleteAll(); @@ -932,7 +933,7 @@ public void sliceShouldTraverseElementsWithoutSkippingOnes() { } @Test // DATAMONGO-1072 - public void shouldBindPlaceholdersUsedAsKeysCorrectly() { + void shouldBindPlaceholdersUsedAsKeysCorrectly() { List persons = repository.findByKeyValue("firstname", alicia.getFirstname()); @@ -940,7 +941,7 @@ public void shouldBindPlaceholdersUsedAsKeysCorrectly() { } @Test // DATAMONGO-1105 - public void returnsOrderedResultsForQuerydslOrderSpecifier() { + void returnsOrderedResultsForQuerydslOrderSpecifier() { Iterable result = repository.findAll(person.firstname.asc()); @@ -948,7 +949,7 @@ public void returnsOrderedResultsForQuerydslOrderSpecifier() { } @Test // DATAMONGO-1085 - public void shouldSupportSortingByQueryDslOrderSpecifier() { + void shouldSupportSortingByQueryDslOrderSpecifier() { repository.deleteAll(); @@ -971,7 +972,7 @@ public void shouldSupportSortingByQueryDslOrderSpecifier() { } @Test // DATAMONGO-1085 - public void shouldSupportSortingWithQSortByQueryDslOrderSpecifier() { + void shouldSupportSortingWithQSortByQueryDslOrderSpecifier() { repository.deleteAll(); @@ -993,7 +994,7 @@ public void shouldSupportSortingWithQSortByQueryDslOrderSpecifier() { } @Test // DATAMONGO-1085 - public void shouldSupportSortingWithQSort() { + void shouldSupportSortingWithQSort() { repository.deleteAll(); @@ -1014,7 +1015,7 @@ public void shouldSupportSortingWithQSort() { } @Test // DATAMONGO-1165 - public void shouldAllowReturningJava8StreamInCustomQuery() { + void shouldAllowReturningJava8StreamInCustomQuery() { Stream result = repository.findByCustomQueryWithStreamingCursorByFirstnames(Arrays.asList("Dave")); @@ -1026,7 +1027,7 @@ public void shouldAllowReturningJava8StreamInCustomQuery() { } @Test // DATAMONGO-1110 - public void executesGeoNearQueryForResultsCorrectlyWhenGivenMinAndMaxDistance() { + void executesGeoNearQueryForResultsCorrectlyWhenGivenMinAndMaxDistance() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -1039,7 +1040,7 @@ public void executesGeoNearQueryForResultsCorrectlyWhenGivenMinAndMaxDistance() } @Test // DATAMONGO-990 - public void shouldFindByFirstnameForSpELExpressionWithParameterIndexOnly() { + void shouldFindByFirstnameForSpELExpressionWithParameterIndexOnly() { List users = repository.findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly("Dave"); @@ -1048,7 +1049,7 @@ public void shouldFindByFirstnameForSpELExpressionWithParameterIndexOnly() { } @Test // DATAMONGO-990 - public void shouldFindByFirstnameAndCurrentUserWithCustomQuery() { + void shouldFindByFirstnameAndCurrentUserWithCustomQuery() { SampleSecurityContextHolder.getCurrent().setPrincipal(dave); List users = repository.findWithSpelByFirstnameAndCurrentUserWithCustomQuery("Dave"); @@ -1058,7 +1059,7 @@ public void shouldFindByFirstnameAndCurrentUserWithCustomQuery() { } @Test // DATAMONGO-990 - public void shouldFindByFirstnameForSpELExpressionWithParameterVariableOnly() { + void shouldFindByFirstnameForSpELExpressionWithParameterVariableOnly() { List users = repository.findWithSpelByFirstnameForSpELExpressionWithParameterVariableOnly("Dave"); @@ -1067,7 +1068,7 @@ public void shouldFindByFirstnameForSpELExpressionWithParameterVariableOnly() { } @Test // DATAMONGO-1911 - public void findByUUIDShouldReturnCorrectResult() { + void findByUUIDShouldReturnCorrectResult() { dave.setUniqueId(UUID.randomUUID()); repository.save(dave); @@ -1078,7 +1079,7 @@ public void findByUUIDShouldReturnCorrectResult() { } @Test // DATAMONGO-1245 - public void findByExampleShouldResolveStuffCorrectly() { + void findByExampleShouldResolveStuffCorrectly() { Person sample = new Person(); sample.setLastname("Matthews"); @@ -1093,7 +1094,7 @@ public void findByExampleShouldResolveStuffCorrectly() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldResolveStuffCorrectly() { + void findAllByExampleShouldResolveStuffCorrectly() { Person sample = new Person(); sample.setLastname("Matthews"); @@ -1108,7 +1109,7 @@ public void findAllByExampleShouldResolveStuffCorrectly() { } @Test // DATAMONGO-1425 - public void findsPersonsByFirstnameNotContains() { + void findsPersonsByFirstnameNotContains() { List result = repository.findByFirstnameNotContains("Boyd"); assertThat(result).hasSize((int) (repository.count() - 1)); @@ -1116,14 +1117,14 @@ public void findsPersonsByFirstnameNotContains() { } @Test // DATAMONGO-1425 - public void findBySkillsContains() { + void findBySkillsContains() { List result = repository.findBySkillsContains(asList("Drums")); assertThat(result).hasSize(1).contains(carter); } @Test // DATAMONGO-1425 - public void findBySkillsNotContains() { + void findBySkillsNotContains() { List result = repository.findBySkillsNotContains(Arrays.asList("Drums")); assertThat(result).hasSize((int) (repository.count() - 1)); @@ -1131,7 +1132,7 @@ public void findBySkillsNotContains() { } @Test // DATAMONGO-1424 - public void findsPersonsByFirstnameNotLike() { + void findsPersonsByFirstnameNotLike() { List result = repository.findByFirstnameNotLike("Bo*"); assertThat(result).hasSize((int) (repository.count() - 1)); @@ -1139,12 +1140,12 @@ public void findsPersonsByFirstnameNotLike() { } @Test // DATAMONGO-1539 - public void countsPersonsByFirstname() { + void countsPersonsByFirstname() { assertThat(repository.countByThePersonsFirstname("Dave")).isEqualTo(1L); } @Test // DATAMONGO-1539 - public void deletesPersonsByFirstname() { + void deletesPersonsByFirstname() { repository.deleteByThePersonsFirstname("Dave"); @@ -1152,50 +1153,50 @@ public void deletesPersonsByFirstname() { } @Test // DATAMONGO-1752 - public void readsOpenProjection() { + void readsOpenProjection() { assertThat(repository.findOpenProjectionBy()).isNotEmpty(); } @Test // DATAMONGO-1752 - public void readsClosedProjection() { + void readsClosedProjection() { assertThat(repository.findClosedProjectionBy()).isNotEmpty(); } @Test // DATAMONGO-1865 - public void findFirstEntityReturnsFirstResultEvenForNonUniqueMatches() { + void findFirstEntityReturnsFirstResultEvenForNonUniqueMatches() { assertThat(repository.findFirstBy()).isNotNull(); } @Test // DATAMONGO-1865 - public void findSingleEntityThrowsErrorWhenNotUnique() { + void findSingleEntityThrowsErrorWhenNotUnique() { assertThatExceptionOfType(IncorrectResultSizeDataAccessException.class) .isThrownBy(() -> repository.findPersonByLastnameLike(dave.getLastname())); } @Test // DATAMONGO-1865 - public void findOptionalSingleEntityThrowsErrorWhenNotUnique() { + void findOptionalSingleEntityThrowsErrorWhenNotUnique() { assertThatExceptionOfType(IncorrectResultSizeDataAccessException.class) .isThrownBy(() -> repository.findOptionalPersonByLastnameLike(dave.getLastname())); } @Test // DATAMONGO-1979 - public void findAppliesAnnotatedSort() { + void findAppliesAnnotatedSort() { assertThat(repository.findByAgeGreaterThan(40)).containsExactly(carter, boyd, dave, leroi); } @Test // DATAMONGO-1979 - public void findWithSortOverwritesAnnotatedSort() { + void findWithSortOverwritesAnnotatedSort() { assertThat(repository.findByAgeGreaterThan(40, Sort.by(Direction.ASC, "age"))).containsExactly(leroi, dave, boyd, carter); } @Test // DATAMONGO-2003 - public void findByRegexWithPattern() { + void findByRegexWithPattern() { assertThat(repository.findByFirstnameRegex(Pattern.compile(alicia.getFirstname()))).hasSize(1); } @Test // DATAMONGO-2003 - public void findByRegexWithPatternAndOptions() { + void findByRegexWithPatternAndOptions() { String fn = alicia.getFirstname().toUpperCase(); @@ -1204,7 +1205,7 @@ public void findByRegexWithPatternAndOptions() { } @Test // DATAMONGO-2149 - public void annotatedQueryShouldAllowSliceInFieldsProjectionWithDbRef() { + void annotatedQueryShouldAllowSliceInFieldsProjectionWithDbRef() { operations.remove(new Query(), User.class); @@ -1227,7 +1228,7 @@ public void annotatedQueryShouldAllowSliceInFieldsProjectionWithDbRef() { } @Test // DATAMONGO-2149 - public void annotatedQueryShouldAllowPositionalParameterInFieldsProjection() { + void annotatedQueryShouldAllowPositionalParameterInFieldsProjection() { Set
      addressList = IntStream.range(0, 10).mapToObj(it -> new Address("street-" + it, "zip", "lnz")) .collect(Collectors.toSet()); @@ -1242,7 +1243,7 @@ public void annotatedQueryShouldAllowPositionalParameterInFieldsProjection() { } @Test // DATAMONGO-2149, DATAMONGO-2154, DATAMONGO-2199 - public void annotatedQueryShouldAllowPositionalParameterInFieldsProjectionWithDbRef() { + void annotatedQueryShouldAllowPositionalParameterInFieldsProjectionWithDbRef() { List userList = IntStream.range(0, 10).mapToObj(it -> { @@ -1265,7 +1266,7 @@ public void annotatedQueryShouldAllowPositionalParameterInFieldsProjectionWithDb } @Test // DATAMONGO-2153 - public void findListOfSingleValue() { + void findListOfSingleValue() { assertThat(repository.findAllLastnames()) // .contains("Lessard") // @@ -1277,7 +1278,7 @@ public void findListOfSingleValue() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithPlaceholderValue() { + void annotatedAggregationWithPlaceholderValue() { assertThat(repository.groupByLastnameAnd("firstname")) .contains(new PersonAggregate("Lessard", Collections.singletonList("Stefan"))) // @@ -1289,7 +1290,7 @@ public void annotatedAggregationWithPlaceholderValue() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithSort() { + void annotatedAggregationWithSort() { assertThat(repository.groupByLastnameAnd("firstname", Sort.by("lastname"))) // .containsSequence( // @@ -1302,7 +1303,7 @@ public void annotatedAggregationWithSort() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithPageable() { + void annotatedAggregationWithPageable() { assertThat(repository.groupByLastnameAnd("firstname", PageRequest.of(1, 2, Sort.by("lastname")))) // .containsExactly( // @@ -1311,12 +1312,12 @@ public void annotatedAggregationWithPageable() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithSingleSimpleResult() { + void annotatedAggregationWithSingleSimpleResult() { assertThat(repository.sumAge()).isEqualTo(245); } @Test // DATAMONGO-2153 - public void annotatedAggregationWithAggregationResultAsReturnType() { + void annotatedAggregationWithAggregationResultAsReturnType() { assertThat(repository.sumAgeAndReturnAggregationResultWrapper()) // .isInstanceOf(AggregationResults.class) // @@ -1324,7 +1325,7 @@ public void annotatedAggregationWithAggregationResultAsReturnType() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithAggregationResultAsReturnTypeAndProjection() { + void annotatedAggregationWithAggregationResultAsReturnTypeAndProjection() { assertThat(repository.sumAgeAndReturnAggregationResultWrapperWithConcreteType()) // .isInstanceOf(AggregationResults.class) // @@ -1332,14 +1333,14 @@ public void annotatedAggregationWithAggregationResultAsReturnTypeAndProjection() } @Test // DATAMONGO-2374 - public void findsWithNativeProjection() { + void findsWithNativeProjection() { assertThat(repository.findDocumentById(dave.getId()).get()).containsEntry("firstname", dave.getFirstname()) .containsEntry("lastname", dave.getLastname()); } @Test // DATAMONGO-1677 - public void findWithMoreThan10Arguments() { + void findWithMoreThan10Arguments() { alicia.setSkills(Arrays.asList("musician", "singer", "composer", "actress", "pianist")); alicia.setAddress(new Address("street", "zipCode", "city")); @@ -1351,9 +1352,8 @@ public void findWithMoreThan10Arguments() { alicia = repository.save(this.alicia); - assertThat(repository.findPersonByManyArguments(this.alicia.getFirstname(), this.alicia.getLastname(), this.alicia.getEmail(), - this.alicia.getAge(), Sex.FEMALE, this.alicia.createdAt, alicia.getSkills(), "street", "zipCode", "city", - alicia.getUniqueId(), credentials.username, credentials.password) - ).isNotNull(); + assertThat(repository.findPersonByManyArguments(this.alicia.getFirstname(), this.alicia.getLastname(), + this.alicia.getEmail(), this.alicia.getAge(), Sex.FEMALE, this.alicia.createdAt, alicia.getSkills(), "street", + "zipCode", "city", alicia.getUniqueId(), credentials.username, credentials.password)).isNotNull(); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index b2e8f6f86d..eca3090702 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -395,9 +395,10 @@ Page findByCustomQueryLastnameAndAddressStreetInList(String lastname, Li @Query(value = "{_id:?0}") Optional findDocumentById(String id); - @Query( - value = "{ 'firstname' : ?0, 'lastname' : ?1, 'email' : ?2 , 'age' : ?3, 'sex' : ?4, 'createdAt' : ?5, 'skills' : ?6, 'address.street' : ?7, 'address.zipCode' : ?8, 'address.city' : ?9, 'uniqueId' : ?10, 'credentials.username' : ?11, 'credentials.password' : ?12 }") + @Query(value = "{ 'firstname' : ?0, 'lastname' : ?1, 'email' : ?2 , 'age' : ?3, 'sex' : ?4, " + + "'createdAt' : ?5, 'skills' : ?6, 'address.street' : ?7, 'address.zipCode' : ?8, " // + + "'address.city' : ?9, 'uniqueId' : ?10, 'credentials.username' : ?11, 'credentials.password' : ?12 }") Person findPersonByManyArguments(String firstname, String lastname, String email, Integer age, Sex sex, - Date createdAt, List skills, String street, String zipCode, String city, UUID uniqueId, String username, - String password); + Date createdAt, List skills, String street, String zipCode, // + String city, UUID uniqueId, String username, String password); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java index 14b8d291d9..76e70edb0b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/RedeclaringRepositoryMethodsTests.java @@ -19,8 +19,7 @@ import java.util.List; -import org.junit.Test; - +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -31,12 +30,12 @@ * @author Mark Paluch */ @ContextConfiguration("config/MongoNamespaceIntegrationTests-context.xml") -public class RedeclaringRepositoryMethodsTests extends AbstractPersonRepositoryIntegrationTests { +class RedeclaringRepositoryMethodsTests extends AbstractPersonRepositoryIntegrationTests { @Autowired RedeclaringRepositoryMethodsRepository repository; @Test // DATAMONGO-760 - public void adjustedWellKnownPagedFindAllMethodShouldReturnOnlyTheUserWithFirstnameOliverAugust() { + void adjustedWellKnownPagedFindAllMethodShouldReturnOnlyTheUserWithFirstnameOliverAugust() { Page page = repository.findAll(PageRequest.of(0, 2)); @@ -45,7 +44,7 @@ public void adjustedWellKnownPagedFindAllMethodShouldReturnOnlyTheUserWithFirstn } @Test // DATAMONGO-760 - public void adjustedWllKnownFindAllMethodShouldReturnAnEmptyList() { + void adjustedWllKnownFindAllMethodShouldReturnAnEmptyList() { List result = repository.findAll(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java index b189938720..7081a93161 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests.java @@ -17,9 +17,8 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionReader; @@ -40,14 +39,14 @@ * @author Oliver Gierke */ @ContextConfiguration -public class MongoNamespaceIntegrationTests extends AbstractPersonRepositoryIntegrationTests { +class MongoNamespaceIntegrationTests extends AbstractPersonRepositoryIntegrationTests { DefaultListableBeanFactory factory; BeanDefinitionReader reader; @Autowired ApplicationContext context; - @Before + @BeforeEach @Override public void setUp() throws InterruptedException { super.setUp(); @@ -56,7 +55,7 @@ public void setUp() throws InterruptedException { } @Test - public void assertDefaultMappingContextIsWired() { + void assertDefaultMappingContextIsWired() { reader.loadBeanDefinitions(new ClassPathResource("MongoNamespaceIntegrationTests-context.xml", getClass())); BeanDefinition definition = factory.getBeanDefinition("personRepository"); @@ -64,7 +63,7 @@ public void assertDefaultMappingContextIsWired() { } @Test // DATAMONGO-581 - public void exposesPersistentEntity() { + void exposesPersistentEntity() { Repositories repositories = new Repositories(context); PersistentEntity entity = repositories.getPersistentEntity(Person.class); From 936a0d35f7a9276d32b277114200fa11576d3e51 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 30 Mar 2020 09:22:53 +0200 Subject: [PATCH 0134/1381] DATAMONGO-2502 - Fix nested array path mapping for updates. Original pull request: #847. --- .../mongodb/core/convert/QueryMapper.java | 33 ++++++------ .../mongodb/core/convert/UpdateMapper.java | 5 +- .../core/DefaultBulkOperationsUnitTests.java | 50 +++++++++++++++++-- .../core/convert/QueryMapperUnitTests.java | 26 ++++++++++ 4 files changed, 93 insertions(+), 21 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 715ba82d5b..91cfc68929 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -922,6 +922,7 @@ public TypeInformation getTypeHint() { */ protected static class MetadataBackedField extends Field { + private static final Pattern POSITIONAL_PARAMETER_PATTERN = Pattern.compile("\\.\\$(\\[.*?\\])?|\\.\\d+"); private static final String INVALID_ASSOCIATION_REFERENCE = "Invalid path reference %s! Associations can only be pointed to directly or via their id property!"; private final MongoPersistentEntity entity; @@ -963,11 +964,15 @@ public MetadataBackedField(String name, MongoPersistentEntity entity, this.entity = entity; this.mappingContext = context; - this.path = getPath(name); + this.path = getPath(removePositionalPlaceholders(name)); this.property = path == null ? property : path.getLeafProperty(); this.association = findAssociation(); } + private static String removePositionalPlaceholders(String raw) { + return POSITIONAL_PARAMETER_PATTERN.matcher(raw).replaceAll(""); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#with(java.lang.String) @@ -1168,7 +1173,7 @@ protected Converter getPropertyConverter() { * @since 1.7 */ protected Converter getAssociationConverter() { - return new AssociationConverter(getAssociation()); + return new AssociationConverter(name, getAssociation()); } protected MappingContext, MongoPersistentProperty> getMappingContext() { @@ -1247,21 +1252,10 @@ protected String mapPropertyName(MongoPersistentProperty property) { StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property)); boolean inspect = iterator.hasNext(); - int depth = 0; while (inspect) { String partial = iterator.next(); - if (depth > 0 && property.isCollectionLike() && property.isEntity() && property.getComponentType() != null) { - - MongoPersistentEntity persistentEntity = mappingContext - .getRequiredPersistentEntity(property.getComponentType()); - MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(partial); - if (persistentProperty != null) { - partial = mapPropertyName(persistentProperty); - } - } - boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike())); if (isPositional) { @@ -1269,13 +1263,12 @@ protected String mapPropertyName(MongoPersistentProperty property) { } inspect = isPositional && iterator.hasNext(); - depth++; } return mappedName.toString(); } - private static boolean isPositionalParameter(String partial) { + static boolean isPositionalParameter(String partial) { if ("$".equals(partial)) { return true; @@ -1303,6 +1296,7 @@ private static boolean isPositionalParameter(String partial) { */ protected static class AssociationConverter implements Converter { + private final String name; private final MongoPersistentProperty property; private boolean associationFound; @@ -1311,10 +1305,11 @@ protected static class AssociationConverter implements Converter association) { + public AssociationConverter(String name, Association association) { Assert.notNull(association, "Association must not be null!"); this.property = association.getInverse(); + this.name = name; } /* @@ -1332,6 +1327,12 @@ public String convert(MongoPersistentProperty source) { associationFound = true; } + if (associationFound) { + if (name.endsWith("$") && property.isCollectionLike()) { + return source.getFieldName() + ".$"; + } + } + return source.getFieldName(); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java index 463c15d4eb..afe13f472a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java @@ -272,6 +272,7 @@ private static Document getSortObject(Sort sort) { * * @author Thomas Darimont * @author Oliver Gierke + * @author Christoph Strobl */ private static class MetadataBackedUpdateField extends MetadataBackedField { @@ -289,7 +290,7 @@ private static class MetadataBackedUpdateField extends MetadataBackedField { public MetadataBackedUpdateField(MongoPersistentEntity entity, String key, MappingContext, MongoPersistentProperty> mappingContext) { - super(key.replaceAll("\\.\\$(\\[.*\\])?", ""), entity, mappingContext); + super(key, entity, mappingContext); this.key = key; } @@ -338,7 +339,7 @@ public UpdateAssociationConverter( MappingContext, MongoPersistentProperty> mappingContext, Association association, String key) { - super(association); + super(key, association); this.mapper = new KeyMapper(key, mappingContext); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 48682071d3..e3f897be17 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -38,7 +38,6 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; - import org.springframework.context.ApplicationEventPublisher; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -233,8 +232,8 @@ void bulkInsertInvokesEntityCallbacks() { verify(beforeSaveCallback).onBeforeSave(personArgumentCaptor.capture(), any(), eq("collection-1")); verify(afterSaveCallback).onAfterSave(personArgumentCaptor.capture(), any(), eq("collection-1")); - assertThat(personArgumentCaptor.getAllValues()).extracting("firstName") - .containsExactly("init", "before-convert", "before-convert"); + assertThat(personArgumentCaptor.getAllValues()).extracting("firstName").containsExactly("init", "before-convert", + "before-convert"); verify(collection).bulkWrite(captor.capture(), any()); InsertOneModel updateModel = (InsertOneModel) captor.getValue().get(0); @@ -340,6 +339,51 @@ void appliesArrayFilterWhenPresent() { .isEqualTo(new org.bson.Document("element", new Document("$gte", 100))); } + @Test // DATAMONGO-2502 + void shouldRetainNestedArrayPathWithPlaceholdersForNoMatchingPaths() { + + ops.updateOne(new BasicQuery("{}"), new Update().set("items.$.documents.0.fileId", "new-id")).execute(); + + verify(collection).bulkWrite(captor.capture(), any()); + + UpdateOneModel updateModel = (UpdateOneModel) captor.getValue().get(0); + assertThat(updateModel.getUpdate()) + .isEqualTo(new Document("$set", new Document("items.$.documents.0.fileId", "new-id"))); + } + + @Test // DATAMONGO-2502 + void shouldRetainNestedArrayPathWithPlaceholdersForMappedEntity() { + + DefaultBulkOperations ops = new DefaultBulkOperations(template, "collection-1", + new BulkOperationContext(BulkMode.ORDERED, Optional.of(mappingContext.getPersistentEntity(OrderTest.class)), + new QueryMapper(converter), new UpdateMapper(converter), null, null)); + + ops.updateOne(new BasicQuery("{}"), Update.update("items.$.documents.0.fileId", "file-id")).execute(); + + verify(collection).bulkWrite(captor.capture(), any()); + + UpdateOneModel updateModel = (UpdateOneModel) captor.getValue().get(0); + assertThat(updateModel.getUpdate()) + .isEqualTo(new Document("$set", new Document("items.$.documents.0.fileId", "file-id"))); + } + + static class OrderTest { + + String id; + List items; + } + + static class OrderTestItem { + + private String cartId; + private List documents; + } + + static class OrderTestDocument { + + private String fileId; + } + class SomeDomainType { @Id String id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 55e3016955..4981d63d4d 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -966,6 +966,32 @@ void mapsCustomFieldNamesForNestedArrayPathCorrectly() { assertThat(target).isEqualTo(new org.bson.Document("arrayCustomName.$[some_item].nes-ted.$[other_item]", "value")); } + @Test // DATAMONGO-2502 + void shouldAllowDeeplyNestedPlaceholders() { + + org.bson.Document target = mapper.getMappedObject( + query(where("level0.$[some_item].arrayObj.$[other_item].nested").is("value")).getQueryObject(), + context.getPersistentEntity(WithDeepArrayNesting.class)); + + assertThat(target).isEqualTo(new org.bson.Document("level0.$[some_item].arrayObj.$[other_item].nested", "value")); + } + + @Test // DATAMONGO-2502 + void shouldAllowDeeplyNestedPlaceholdersWithCustomName() { + + org.bson.Document target = mapper.getMappedObject( + query(where("level0.$[some_item].arrayCustomName.$[other_item].nested").is("value")).getQueryObject(), + context.getPersistentEntity(WithDeepArrayNesting.class)); + + assertThat(target) + .isEqualTo(new org.bson.Document("level0.$[some_item].arrayCustomName.$[other_item].nes-ted", "value")); + } + + class WithDeepArrayNesting { + + List level0; + } + class WithNestedArray { List arrayObj; From c5501db5772dc21238152bd5dd8b7c8cbc918e18 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 7 Apr 2020 14:09:43 +0200 Subject: [PATCH 0135/1381] DATAMONGO-2502 - Polishing. Extend tests. Fix generics. Consistently use compiled patterns for positional placeholder removal. Original pull request: #847. --- .../mongodb/core/convert/QueryMapper.java | 23 +++++++++---------- .../core/DefaultBulkOperationsUnitTests.java | 3 ++- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 91cfc68929..ec18d07677 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -419,7 +419,7 @@ protected boolean isAssociationConversionNecessary(Field documentField, @Nullabl return false; } - Class type = value.getClass(); + Class type = value.getClass(); MongoPersistentProperty property = documentField.getProperty(); if (property.getActualType().isAssignableFrom(type)) { @@ -443,7 +443,7 @@ protected boolean isAssociationConversionNecessary(Field documentField, @Nullabl protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersistentEntity entity) { if (source instanceof Example) { - return exampleMapper.getMappedExample((Example) source, entity); + return exampleMapper.getMappedExample((Example) source, entity); } if (source instanceof List) { @@ -923,6 +923,7 @@ public TypeInformation getTypeHint() { protected static class MetadataBackedField extends Field { private static final Pattern POSITIONAL_PARAMETER_PATTERN = Pattern.compile("\\.\\$(\\[.*?\\])?|\\.\\d+"); + private static final Pattern DOT_POSITIONAL_PATTERN = Pattern.compile("\\.\\d+"); private static final String INVALID_ASSOCIATION_REFERENCE = "Invalid path reference %s! Associations can only be pointed to directly or via their id property!"; private final MongoPersistentEntity entity; @@ -964,15 +965,11 @@ public MetadataBackedField(String name, MongoPersistentEntity entity, this.entity = entity; this.mappingContext = context; - this.path = getPath(removePositionalPlaceholders(name)); + this.path = getPath(removePlaceholders(POSITIONAL_PARAMETER_PATTERN, name)); this.property = path == null ? property : path.getLeafProperty(); this.association = findAssociation(); } - private static String removePositionalPlaceholders(String raw) { - return POSITIONAL_PARAMETER_PATTERN.matcher(raw).replaceAll(""); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#with(java.lang.String) @@ -1076,7 +1073,7 @@ protected PersistentPropertyPath getPath() { } /** - * Returns the {@link PersistentPropertyPath} for the given pathExpression. + * Returns the {@link PersistentPropertyPath} for the given {@code pathExpression}. * * @param pathExpression * @return @@ -1084,8 +1081,8 @@ protected PersistentPropertyPath getPath() { @Nullable private PersistentPropertyPath getPath(String pathExpression) { - String rawPath = pathExpression.replaceAll("\\.\\d+", "") // - .replaceAll(POSITIONAL_OPERATOR.pattern(), ""); + String rawPath = removePlaceholders(POSITIONAL_OPERATOR, + removePlaceholders(DOT_POSITIONAL_PATTERN, pathExpression)); PropertyPath path = forName(rawPath); if (path == null || isPathToJavaLangClassProperty(path)) { @@ -1180,6 +1177,10 @@ protected MappingContext, MongoPersistentProp return mappingContext; } + private static String removePlaceholders(Pattern pattern, String raw) { + return pattern.matcher(raw).replaceAll(""); + } + /** * @author Christoph Strobl * @since 1.8 @@ -1231,14 +1232,12 @@ public TypeInformation getTypeHint() { static class KeyMapper { private final Iterator iterator; - private final MappingContext, MongoPersistentProperty> mappingContext; public KeyMapper(String key, MappingContext, MongoPersistentProperty> mappingContext) { this.iterator = Arrays.asList(key.split("\\.")).iterator(); this.iterator.next(); - this.mappingContext = mappingContext; } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index e3f897be17..4b9cd57fcd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -364,7 +364,7 @@ void shouldRetainNestedArrayPathWithPlaceholdersForMappedEntity() { UpdateOneModel updateModel = (UpdateOneModel) captor.getValue().get(0); assertThat(updateModel.getUpdate()) - .isEqualTo(new Document("$set", new Document("items.$.documents.0.fileId", "file-id"))); + .isEqualTo(new Document("$set", new Document("items.$.documents.0.the_file_id", "file-id"))); } static class OrderTest { @@ -381,6 +381,7 @@ static class OrderTestItem { static class OrderTestDocument { + @Field("the_file_id") private String fileId; } From 4b3312998a9306cbb3bc5a76fea6e8ed597f0610 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 7 Apr 2020 14:23:38 +0200 Subject: [PATCH 0136/1381] DATAMONGO-2506 - Provide meaningful error message when using unsupported return type in repository aggregation method. We improved the error message for unsupported return types instead of running into an IllegalArgumentException for unique results. Original pull request: #851. --- .../query/StringBasedAggregation.java | 5 +++++ .../StringBasedAggregationUnitTests.java | 21 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java index 9709874fe6..912f0e3c9f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java @@ -20,6 +20,7 @@ import org.bson.Document; +import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; @@ -71,6 +72,10 @@ public StringBasedAggregation(MongoQueryMethod method, MongoOperations mongoOper protected Object doExecute(MongoQueryMethod method, ResultProcessor resultProcessor, ConvertingParameterAccessor accessor, Class typeToRead) { + if (method.isPageQuery() || method.isSliceQuery()) { + throw new InvalidMongoDbApiUsageException(String.format("Repository aggregation method '%s' does not support '%s' return type. Please use eg. 'List' instead.", method.getName(), method.getReturnType().getType().getSimpleName())); + } + Class sourceType = method.getDomainClass(); Class targetType = typeToRead; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java index 568e455c7a..c24701deab 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java @@ -34,9 +34,14 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; - +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; @@ -68,6 +73,7 @@ * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class StringBasedAggregationUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -202,6 +208,16 @@ public void aggregateWithCollationParameter() { assertThat(collationOf(invocation)).isEqualTo(Collation.of("en_US")); } + @Test // DATAMONGO-2506 + public void aggregateRaisesErrorOnInvalidReturnType() { + + StringBasedAggregation sba = createAggregationForMethod("invalidPageReturnType", Pageable.class); + assertThatExceptionOfType(InvalidMongoDbApiUsageException.class) // + .isThrownBy(() -> sba.execute(new Object[] { PageRequest.of(0, 1) })) // + .withMessageContaining("invalidPageReturnType") // + .withMessageContaining("Page"); + } + private AggregationInvocation executeAggregation(String name, Object... args) { Class[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new); @@ -280,6 +296,9 @@ private interface SampleRepository extends Repository { @Aggregation(pipeline = RAW_GROUP_BY_LASTNAME_STRING, collation = "de_AT") PersonAggregate aggregateWithCollation(Collation collation); + + @Aggregation(RAW_GROUP_BY_LASTNAME_STRING) + Page invalidPageReturnType(Pageable page); } static class PersonAggregate { From a1b4e6df59e9e057b855ce74c8ba32d9cb0567b3 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Apr 2020 11:38:19 +0200 Subject: [PATCH 0137/1381] DATAMONGO-2508 - Upgrade to MongoDB 4.0.2 Drivers. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 78d003846a..e5e41bf08c 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 4.0.1 + 4.0.2 ${mongo} 1.19 From bf921cdbd7909edfdfcbf1234dc2808560bd59ea Mon Sep 17 00:00:00 2001 From: Greg Turnquist Date: Thu, 9 Apr 2020 14:29:16 -0500 Subject: [PATCH 0138/1381] DATAMONGO-2510 - Use JDK 14 for Java.NEXT CI testing. --- Jenkinsfile | 10 +++++----- .../Dockerfile | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename ci/{openjdk13-mongodb-4.2 => openjdk14-mongodb-4.2}/Dockerfile (94%) diff --git a/Jenkinsfile b/Jenkinsfile index ca8038866a..62ea203246 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,16 +46,16 @@ pipeline { } } } - stage('Publish JDK 13 + MongoDB 4.2') { + stage('Publish JDK 14 + MongoDB 4.2') { when { - changeset "ci/openjdk13-mongodb-4.2/**" + changeset "ci/openjdk14-mongodb-4.2/**" } agent { label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { script { - def image = docker.build("springci/spring-data-openjdk13-with-mongodb-4.2.0", "ci/openjdk13-mongodb-4.2/") + def image = docker.build("springci/spring-data-openjdk14-with-mongodb-4.2.0", "ci/openjdk14-mongodb-4.2/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } @@ -139,10 +139,10 @@ pipeline { } } - stage("test: baseline (jdk13)") { + stage("test: baseline (jdk14)") { agent { docker { - image 'springci/spring-data-openjdk13-with-mongodb-4.2.0:latest' + image 'springci/spring-data-openjdk14-with-mongodb-4.2.0:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } diff --git a/ci/openjdk13-mongodb-4.2/Dockerfile b/ci/openjdk14-mongodb-4.2/Dockerfile similarity index 94% rename from ci/openjdk13-mongodb-4.2/Dockerfile rename to ci/openjdk14-mongodb-4.2/Dockerfile index 7987bdb73c..5f7d26c929 100644 --- a/ci/openjdk13-mongodb-4.2/Dockerfile +++ b/ci/openjdk14-mongodb-4.2/Dockerfile @@ -1,4 +1,4 @@ -FROM adoptopenjdk/openjdk13:latest +FROM adoptopenjdk/openjdk14:latest ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive From c6630aa279d00dbcd66e4d99186e1ae484016be4 Mon Sep 17 00:00:00 2001 From: Juergen Zimmermann Date: Tue, 7 Apr 2020 19:36:21 +0200 Subject: [PATCH 0139/1381] DATAMONGO-2507 - Add default method matching(CriteriaDefinition) to ReactiveFindOperation.DistinctWithQuery. Original Pull Request: #852 --- .../data/mongodb/core/ReactiveFindOperation.java | 13 +++++++++++++ .../core/ReactiveFindOperationSupportTests.java | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index a96c6b1062..8cc56a7e73 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -46,6 +46,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Juergen Zimmermann * @since 2.0 */ public interface ReactiveFindOperation { @@ -275,6 +276,18 @@ interface DistinctWithQuery extends DistinctWithProjection { * @throws IllegalArgumentException if resultType is {@literal null}. */ TerminatingDistinct matching(Query query); + + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteriaDefinition must not be {@literal null}. + * @return new instance of {@link TerminatingFind}. + * @throws IllegalArgumentException if query is {@literal null}. + * @since 3.0 + */ + default TerminatingDistinct matching(CriteriaDefinition criteriaDefinition) { + return matching(Query.query(criteriaDefinition)); + } } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java index e2e200c96a..a2eb572753 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java @@ -59,6 +59,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Juergen Zimmermann */ @ExtendWith(MongoClientExtension.class) class ReactiveFindOperationSupportTests { @@ -171,6 +172,14 @@ void findAllByCriteria() { .verifyComplete(); } + @Test // DATAMONGO-2507 + void findAllWithProjectionByCriteria() { + + template.query(Person.class).as(Jedi.class).matching(where("firstname").is("luke")).all() + .as(StepVerifier::create).consumeNextWith(it -> assertThat(it).isInstanceOf(Jedi.class)) // + .verifyComplete(); + } + @Test // DATAMONGO-1719 void findAllByWithCollectionUsingMappingInformation() { From e1df28797a94b10ac8d6bb773d31bc0946284dfb Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 14 Apr 2020 10:22:01 +0200 Subject: [PATCH 0140/1381] DATAMONGO-2507 - Polishing. Add 'matching' default method also to imperative variant (ExecutableFindOperation), fix & add tests using 'distinct'. Update Javadoc and rename input arg 'criteriaDefinition' to 'criteria'. Original Pull Request: #852 --- .../mongodb/core/ExecutableFindOperation.java | 24 ++++++++++++++----- .../core/ExecutableMapReduceOperation.java | 6 ++--- .../core/ExecutableRemoveOperation.java | 6 ++--- .../core/ExecutableUpdateOperation.java | 6 ++--- .../mongodb/core/ReactiveFindOperation.java | 22 ++++++++--------- .../core/ReactiveMapReduceOperation.java | 6 ++--- .../mongodb/core/ReactiveRemoveOperation.java | 6 ++--- .../mongodb/core/ReactiveUpdateOperation.java | 6 ++--- .../ExecutableFindOperationSupportTests.java | 10 ++++++++ .../ReactiveFindOperationSupportTests.java | 19 ++++++++------- 10 files changed, 68 insertions(+), 43 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index 86ed2e52ff..b2d4e729e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -44,7 +44,7 @@ * query(Human.class) * .inCollection("star-wars") * .as(Jedi.class) - * .matching(query(where("firstname").is("luke"))) + * .matching(where("firstname").is("luke")) * .all(); * * @@ -174,13 +174,13 @@ interface FindWithQuery extends TerminatingFind { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link TerminatingFind}. - * @throws IllegalArgumentException if query is {@literal null}. + * @throws IllegalArgumentException if criteria is {@literal null}. * @since 3.0 */ - default TerminatingFind matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingFind matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } /** @@ -304,9 +304,21 @@ interface DistinctWithQuery extends DistinctWithProjection { * * @param query must not be {@literal null}. * @return new instance of {@link TerminatingDistinct}. - * @throws IllegalArgumentException if resultType is {@literal null}. + * @throws IllegalArgumentException if query is {@literal null}. */ TerminatingDistinct matching(Query query); + + /** + * Set the filter {@link CriteriaDefinition criteria} to be used. + * + * @param criteria must not be {@literal null}. + * @return new instance of {@link TerminatingDistinct}. + * @throws IllegalArgumentException if criteria is {@literal null}. + * @since 3.0 + */ + default TerminatingDistinct matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); + } } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java index 73ecb66bed..be43d25a85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java @@ -152,13 +152,13 @@ interface MapReduceWithQuery extends TerminatingMapReduce { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link TerminatingMapReduce}. * @throws IllegalArgumentException if query is {@literal null}. * @since 3.0 */ - default TerminatingMapReduce matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingMapReduce matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java index 5f4fb8d9d5..5c95c469e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java @@ -124,13 +124,13 @@ interface RemoveWithQuery extends TerminatingRemove { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link TerminatingRemove}. * @throws IllegalArgumentException if query is {@literal null}. * @since 3.0 */ - default TerminatingRemove matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingRemove matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index b3c9b084a2..7b45b10680 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -215,13 +215,13 @@ interface UpdateWithQuery extends UpdateWithUpdate { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link UpdateWithUpdate}. * @throws IllegalArgumentException if query is {@literal null}. * @since 3.0 */ - default UpdateWithUpdate matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default UpdateWithUpdate matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index 8cc56a7e73..d9cdb3f257 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -39,7 +39,7 @@ * query(Human.class) * .inCollection("star-wars") * .as(Jedi.class) - * .matching(query(where("firstname").is("luke"))) + * .matching(where("firstname").is("luke")) * .all(); * * @@ -149,13 +149,13 @@ interface FindWithQuery extends TerminatingFind { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link TerminatingFind}. - * @throws IllegalArgumentException if query is {@literal null}. + * @throws IllegalArgumentException if criteria is {@literal null}. * @since 3.0 */ - default TerminatingFind matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingFind matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } /** @@ -273,20 +273,20 @@ interface DistinctWithQuery extends DistinctWithProjection { * * @param query must not be {@literal null}. * @return new instance of {@link TerminatingDistinct}. - * @throws IllegalArgumentException if resultType is {@literal null}. + * @throws IllegalArgumentException if query is {@literal null}. */ TerminatingDistinct matching(Query query); /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. - * @return new instance of {@link TerminatingFind}. - * @throws IllegalArgumentException if query is {@literal null}. + * @param criteria must not be {@literal null}. + * @return new instance of {@link TerminatingDistinct}. + * @throws IllegalArgumentException if criteria is {@literal null}. * @since 3.0 */ - default TerminatingDistinct matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingDistinct matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java index 12f71eb24d..34a41cdc56 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java @@ -151,13 +151,13 @@ interface MapReduceWithQuery extends TerminatingMapReduce { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link TerminatingMapReduce}. * @throws IllegalArgumentException if query is {@literal null}. * @since 3.0 */ - default TerminatingMapReduce matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingMapReduce matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java index f3c3421e32..499592a437 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java @@ -111,13 +111,13 @@ interface RemoveWithQuery extends TerminatingRemove { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link TerminatingRemove}. * @throws IllegalArgumentException if query is {@literal null}. * @since 3.0 */ - default TerminatingRemove matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default TerminatingRemove matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java index cb8c154b07..74aa29799a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java @@ -176,13 +176,13 @@ interface UpdateWithQuery extends UpdateWithUpdate { /** * Set the filter {@link CriteriaDefinition criteria} to be used. * - * @param criteriaDefinition must not be {@literal null}. + * @param criteria must not be {@literal null}. * @return new instance of {@link UpdateWithUpdate}. * @throws IllegalArgumentException if query is {@literal null}. * @since 3.0 */ - default UpdateWithUpdate matching(CriteriaDefinition criteriaDefinition) { - return matching(Query.query(criteriaDefinition)); + default UpdateWithUpdate matching(CriteriaDefinition criteria) { + return matching(Query.query(criteria)); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java index 65fae75e61..e972b3eb34 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java @@ -536,6 +536,16 @@ void distinctThrowsExceptionWhenExplicitMappingTypeCannotBeApplied() { .isThrownBy(() -> template.query(Person.class).distinct("firstname").as(Long.class).all()); } + @Test // DATAMONGO-2507 + void distinctAppliesFilterQuery() { + + assertThat(template.query(Person.class).inCollection(STAR_WARS).distinct("firstname") // + .matching(where("lastname").is(luke.lastname)) // + .as(String.class) // + .all() // + ).containsExactlyInAnyOrder("luke"); + } + interface Contact {} @Data diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java index a2eb572753..8b48bb67e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java @@ -172,14 +172,6 @@ void findAllByCriteria() { .verifyComplete(); } - @Test // DATAMONGO-2507 - void findAllWithProjectionByCriteria() { - - template.query(Person.class).as(Jedi.class).matching(where("firstname").is("luke")).all() - .as(StepVerifier::create).consumeNextWith(it -> assertThat(it).isInstanceOf(Jedi.class)) // - .verifyComplete(); - } - @Test // DATAMONGO-1719 void findAllByWithCollectionUsingMappingInformation() { @@ -640,6 +632,17 @@ void distinctThrowsExceptionWhenExplicitMappingTypeCannotBeApplied() { .verify(); } + @Test // DATAMONGO-2507 + void distinctAppliesFilterQuery() { + + template.query(Person.class).inCollection(STAR_WARS).distinct("firstname") // + .matching(where("lastname").is(luke.lastname)) // + .as(String.class) // + .all() // + .as(StepVerifier::create).consumeNextWith(it -> assertThat(it).isEqualTo("luke")) // + .verifyComplete(); + } + interface Contact {} @Data From 6604c507ddfaffd8fd9f46b9a6d220fd2a3fd11d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 17 Apr 2020 11:15:42 +0200 Subject: [PATCH 0141/1381] DATAMONGO-2517 - Fix invalid entity creation for text queries. Fix a glitch in the MappingMongoConverter that uses the single String argument constructor (since it matches in type and parameter count to the given input string) to falsely instantiate an Entity when it should not. Original pull request: #857. --- .../core/convert/MappingMongoConverter.java | 9 +++++--- .../core/convert/QueryMapperUnitTests.java | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) 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 a23e4849a5..d9dd171f2f 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 @@ -1283,9 +1283,12 @@ public Object convertToMongoType(@Nullable Object obj, TypeInformation typeIn } if (conversions.isSimpleType(obj.getClass())) { - // Doesn't need conversion - return getPotentiallyConvertedSimpleWrite(obj, - typeInformation != null ? typeInformation.getType() : Object.class); + + Class conversionTargetType = Object.class; + if(typeInformation != null && conversions.isSimpleType(typeInformation.getType())) { + conversionTargetType = typeInformation.getType(); + } + return getPotentiallyConvertedSimpleWrite(obj, conversionTargetType); } if (obj instanceof List) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 4981d63d4d..d33ac9d7ba 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -56,6 +56,7 @@ import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.TextQuery; import com.mongodb.BasicDBObject; import com.mongodb.MongoClientSettings; @@ -987,6 +988,16 @@ void shouldAllowDeeplyNestedPlaceholdersWithCustomName() { .isEqualTo(new org.bson.Document("level0.$[some_item].arrayCustomName.$[other_item].nes-ted", "value")); } + @Test // DATAMONGO-2517 + public void shouldParseNestedKeywordWithArgumentMatchingTheSourceEntitiesConstructorCorrectly() { + + TextQuery source = new TextQuery("test"); + + org.bson.Document target = mapper.getMappedObject(source.getQueryObject(), + context.getPersistentEntity(WithSingleStringArgConstructor.class)); + assertThat(target).isEqualTo(org.bson.Document.parse("{\"$text\" : { \"$search\" : \"test\" }}")); + } + class WithDeepArrayNesting { List level0; @@ -1158,4 +1169,16 @@ static class NonIdFieldWithObjectIdTargetType { String id; @Field(targetType = FieldType.OBJECT_ID) String stringAsOid; } + + @Document + static class WithSingleStringArgConstructor { + + String value; + + public WithSingleStringArgConstructor() {} + + public WithSingleStringArgConstructor(String value) { + this.value = value; + } + } } From b57e5710335c3a83f16b2919d7a239517b1efc65 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 21 Apr 2020 16:01:52 +0200 Subject: [PATCH 0142/1381] DATAMONGO-2517 - Polishing. Reformat code. Original pull request: #857. --- .../data/mongodb/core/convert/MappingMongoConverter.java | 8 ++++++-- .../data/mongodb/core/convert/QueryMapperUnitTests.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) 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 d9dd171f2f..592046bdd3 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 @@ -1284,10 +1284,14 @@ public Object convertToMongoType(@Nullable Object obj, TypeInformation typeIn if (conversions.isSimpleType(obj.getClass())) { - Class conversionTargetType = Object.class; - if(typeInformation != null && conversions.isSimpleType(typeInformation.getType())) { + Class conversionTargetType; + + if (typeInformation != null && conversions.isSimpleType(typeInformation.getType())) { conversionTargetType = typeInformation.getType(); + } else { + conversionTargetType = Object.class; } + return getPotentiallyConvertedSimpleWrite(obj, conversionTargetType); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index d33ac9d7ba..0a623dd78e 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -989,7 +989,7 @@ void shouldAllowDeeplyNestedPlaceholdersWithCustomName() { } @Test // DATAMONGO-2517 - public void shouldParseNestedKeywordWithArgumentMatchingTheSourceEntitiesConstructorCorrectly() { + void shouldParseNestedKeywordWithArgumentMatchingTheSourceEntitiesConstructorCorrectly() { TextQuery source = new TextQuery("test"); From 32f3e60c9fc6fad0ff46211cecc3d24e329af02f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 21 Apr 2020 10:08:59 +0200 Subject: [PATCH 0143/1381] DATAMONGO-2523 - Fix Json binding of SpEL expressions in arrays. The closing bracket must not have a leading whitespace. Original pull request: #859. --- .../data/mongodb/util/json/JsonScanner.java | 2 +- .../util/json/ParameterBindingJsonReaderUnitTests.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java index 683da25753..b49403ee62 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java @@ -231,7 +231,7 @@ private JsonToken scanBindString() { parenthesisCount--; if (parenthesisCount == 0) { - buffer.read(); + c = buffer.read(); break; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index b1ebc295d8..c3257b5f71 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -256,6 +256,14 @@ void bindQuotedMulitParameterInArray() { .isEqualTo(new Document("name", new Document("$in", Collections.singletonList("dalinar,kohlin")))); } + @Test // DATAMONGO-2523 + void bindSpelExpressionInArrayCorrectly/* closing bracket must not have leading whitespace! */() { + + Document target = parse("{ $and : [?#{ [0] == null ? { '$where' : 'true' } : { 'v1' : { '$in' : {[0]} } } }]}", 1); + + assertThat(target).isEqualTo(Document.parse("{\"$and\": [{\"v1\": {\"$in\": [1]}}]}")); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); From 95c47079029d3aa9d1a8b9e7500cb6b7e5c91eb1 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 Apr 2020 10:08:25 +0200 Subject: [PATCH 0144/1381] DATAMONGO-2523 - Polishing. Reformat code. Original pull request: #859. From fba6d7d8be36277b149133cf8e866b1fe08e9bc2 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 16 Apr 2020 14:02:08 +0200 Subject: [PATCH 0145/1381] DATAMONGO-2516 - Assert compatibility with MongoDB 4.4-rc0. Fixes: - Fields list must not contain text search score property when no $text criteria present. - Sort must not be an empty document when running map reduce. - Timeout in tests creating indexes. Changes: - score property might now be null when not having a $text criteria present. Was zero before. Original pull request: #856. --- .../data/mongodb/core/MongoTemplate.java | 49 ++++++++----------- .../data/mongodb/core/QueryOperations.java | 44 +++++++++++++---- .../mongodb/core/ReactiveMongoTemplate.java | 30 ++++++++---- .../core/ReactiveMongoTemplateIndexTests.java | 5 +- .../core/UpdateOperationsUnitTests.java | 7 +-- ...oRepositoryTextSearchIntegrationTests.java | 4 +- 6 files changed, 85 insertions(+), 54 deletions(-) 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 332ec87e85..ea858d2dee 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.GroupByResults; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; import org.springframework.data.mongodb.core.mapreduce.MapReduceResults; +import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Meta; @@ -238,7 +239,7 @@ public MongoTemplate(MongoDatabaseFactory mongoDbFactory, @Nullable MongoConvert this.projectionFactory = new SpelAwareProxyProjectionFactory(); this.operations = new EntityOperations(this.mongoConverter.getMappingContext()); this.propertyOperations = new PropertyOperations(this.mongoConverter.getMappingContext()); - this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, mongoDbFactory); + this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, propertyOperations, mongoDbFactory); // We always have a mapping context in the converter, whether it's a simple one or not mappingContext = this.mongoConverter.getMappingContext(); @@ -424,8 +425,10 @@ protected CloseableIterator doStream(Query query, Class entityType, St MongoPersistentEntity persistentEntity = mappingContext.getPersistentEntity(entityType); - Document mappedFields = getMappedFieldsObject(query.getFieldsObject(), persistentEntity, returnType); - Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), persistentEntity); + QueryContext queryContext = queryOperations.createQueryContext(query); + + Document mappedQuery = queryContext.getMappedQuery(persistentEntity); + Document mappedFields = queryContext.getMappedFields(persistentEntity, returnType, projectionFactory); FindIterable cursor = new QueryCursorPreparer(query, entityType).initiateFind(collection, col -> col.find(mappedQuery, Document.class).projection(mappedFields)); @@ -1054,7 +1057,7 @@ public T findAndReplace(Query query, S replacement, FindAndReplaceOptions QueryContext queryContext = queryOperations.createQueryContext(query); Document mappedQuery = queryContext.getMappedQuery(entity); - Document mappedFields = queryContext.getMappedFields(entity); + Document mappedFields = queryContext.getMappedFields(entity, resultType, projectionFactory); Document mappedSort = queryContext.getMappedSort(entity); replacement = maybeCallBeforeConvert(replacement, collectionName); @@ -1819,7 +1822,11 @@ public List mapReduce(Query query, Class domainType, String inputColle if (query.getMeta().getMaxTimeMsec() != null) { mapReduce = mapReduce.maxTime(query.getMeta().getMaxTimeMsec(), TimeUnit.MILLISECONDS); } - mapReduce = mapReduce.sort(getMappedSortObject(query, domainType)); + + Document mappedSort = getMappedSortObject(query, domainType); + if(mappedSort != null && !mappedSort.isEmpty()) { + mapReduce = mapReduce.sort(getMappedSortObject(query, domainType)); + } mapReduce = mapReduce .filter(queryMapper.getMappedObject(query.getQueryObject(), mappingContext.getPersistentEntity(domainType))); @@ -2435,8 +2442,9 @@ protected T doFindOne(String collectionName, Document query, Document fields MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - Document mappedQuery = queryMapper.getMappedObject(query, entity); - Document mappedFields = queryMapper.getMappedObject(fields, entity); + QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields)); + Document mappedFields = queryContext.getMappedFields(entity, entityClass, projectionFactory); + Document mappedQuery = queryContext.getMappedQuery(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug("findOne using query: {} fields: {} for class: {} in collection: {}", serializeToJsonSafely(query), @@ -2486,8 +2494,9 @@ protected List doFind(String collectionName, Document query, Document MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - Document mappedFields = queryMapper.getMappedFields(fields, entity); - Document mappedQuery = queryMapper.getMappedObject(query, entity); + QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields)); + Document mappedFields = queryContext.getMappedFields(entity, entityClass, projectionFactory); + Document mappedQuery = queryContext.getMappedQuery(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug("find using query: {} fields: {} for class: {} in collection: {}", @@ -2509,8 +2518,9 @@ List doFind(String collectionName, Document query, Document fields, Cl MongoPersistentEntity entity = mappingContext.getPersistentEntity(sourceClass); - Document mappedFields = getMappedFieldsObject(fields, entity, targetClass); - Document mappedQuery = queryMapper.getMappedObject(query, entity); + QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields)); + Document mappedFields = queryContext.getMappedFields(entity, targetClass, projectionFactory); + Document mappedQuery = queryContext.getMappedQuery(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug("find using query: {} fields: {} for class: {} in collection: {}", @@ -2839,23 +2849,6 @@ private Document getMappedSortObject(Query query, Class type) { return queryMapper.getMappedSort(query.getSortObject(), mappingContext.getPersistentEntity(type)); } - private Document getMappedFieldsObject(Document fields, @Nullable MongoPersistentEntity entity, - Class targetType) { - - if (entity == null) { - return fields; - } - - Document projectedFields = propertyOperations.computeFieldsForProjection(projectionFactory, fields, - entity.getType(), targetType); - - if (ObjectUtils.nullSafeEquals(fields, projectedFields)) { - return queryMapper.getMappedFields(projectedFields, entity); - } - - return queryMapper.getMappedFields(projectedFields, mappingContext.getRequiredPersistentEntity(targetType)); - } - /** * Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original * exception if the conversation failed. Thus allows safe re-throwing of the return value. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index 357f1bddec..438e53c5dc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -47,8 +47,10 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; import org.springframework.data.mongodb.util.BsonUtils; +import org.springframework.data.projection.ProjectionFactory; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import com.mongodb.client.model.CountOptions; @@ -70,6 +72,7 @@ class QueryOperations { private final QueryMapper queryMapper; private final UpdateMapper updateMapper; private final EntityOperations entityOperations; + private final PropertyOperations propertyOperations; private final CodecRegistryProvider codecRegistryProvider; private final MappingContext, MongoPersistentProperty> mappingContext; private final AggregationUtil aggregationUtil; @@ -81,14 +84,16 @@ class QueryOperations { * @param queryMapper must not be {@literal null}. * @param updateMapper must not be {@literal null}. * @param entityOperations must not be {@literal null}. + * @param propertyOperations must not be {@literal null}. * @param codecRegistryProvider must not be {@literal null}. */ QueryOperations(QueryMapper queryMapper, UpdateMapper updateMapper, EntityOperations entityOperations, - CodecRegistryProvider codecRegistryProvider) { + PropertyOperations propertyOperations, CodecRegistryProvider codecRegistryProvider) { this.queryMapper = queryMapper; this.updateMapper = updateMapper; this.entityOperations = entityOperations; + this.propertyOperations = propertyOperations; this.codecRegistryProvider = codecRegistryProvider; this.mappingContext = queryMapper.getMappingContext(); this.aggregationUtil = new AggregationUtil(queryMapper, mappingContext); @@ -250,14 +255,31 @@ Document getMappedQuery(@Nullable MongoPersistentEntity entity) { return queryMapper.getMappedObject(getQueryObject(), entity); } - /** - * Get the already mapped {@link Query#getFieldsObject() fields projection} - * - * @param entity the Entity to map field names to. Can be {@literal null}. - * @return never {@literal null}. - */ - Document getMappedFields(@Nullable MongoPersistentEntity entity) { - return queryMapper.getMappedFields(query.getFieldsObject(), entity); + Document getMappedFields(@Nullable MongoPersistentEntity entity, Class targetType, + ProjectionFactory projectionFactory) { + + Document fields = query.getFieldsObject(); + Document mappedFields = fields; + + if (entity == null) { + return mappedFields; + } + + Document projectedFields = propertyOperations.computeFieldsForProjection(projectionFactory, fields, + entity.getType(), targetType); + + if (ObjectUtils.nullSafeEquals(fields, projectedFields)) { + mappedFields = queryMapper.getMappedFields(projectedFields, entity); + } else { + mappedFields = queryMapper.getMappedFields(projectedFields, + mappingContext.getRequiredPersistentEntity(targetType)); + } + + if (entity != null && entity.hasTextScoreProperty() && !query.getQueryObject().containsKey("$text")) { + mappedFields.remove(entity.getTextScoreProperty().getFieldName()); + } + + return mappedFields; } /** @@ -319,6 +341,10 @@ private DistinctQueryContext(@Nullable Object query, String fieldName) { } @Override + Document getMappedFields(@Nullable MongoPersistentEntity entity, Class targetType, ProjectionFactory projectionFactory) { + return getMappedFields(entity); + } + Document getMappedFields(@Nullable MongoPersistentEntity entity) { return queryMapper.getMappedFields(new Document(fieldName, 1), entity); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index c35f02e5be..baddbb2b5d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -39,7 +39,6 @@ import org.reactivestreams.Subscriber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -94,6 +93,7 @@ import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; import org.springframework.data.mongodb.core.mapping.event.*; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; +import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Meta; import org.springframework.data.mongodb.core.query.Meta.CursorOption; @@ -258,7 +258,8 @@ public ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory, this.mappingContext = this.mongoConverter.getMappingContext(); this.operations = new EntityOperations(this.mappingContext); this.propertyOperations = new PropertyOperations(this.mappingContext); - this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, mongoDatabaseFactory); + this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, propertyOperations, + mongoDatabaseFactory); // We create indexes based on mapping events if (this.mappingContext instanceof MongoMappingContext) { @@ -1161,7 +1162,7 @@ public Mono findAndReplace(Query query, S replacement, FindAndReplaceO QueryContext queryContext = queryOperations.createQueryContext(query); Document mappedQuery = queryContext.getMappedQuery(entity); - Document mappedFields = queryContext.getMappedFields(entity); + Document mappedFields = queryContext.getMappedFields(entity, resultType, projectionFactory); Document mappedSort = queryContext.getMappedSort(entity); return Mono.defer(() -> { @@ -2152,7 +2153,11 @@ public Flux mapReduce(Query filterQuery, Class domainType, String inpu MapReducePublisher publisher = collection.mapReduce(mapFunction, reduceFunction, Document.class); publisher.filter(mappedQuery); - publisher.sort(getMappedSortObject(filterQuery, domainType)); + + Document mappedSort = getMappedSortObject(filterQuery, domainType); + if (mappedSort != null && !mappedSort.isEmpty()) { + publisher.sort(mappedSort); + } if (filterQuery.getMeta().getMaxTimeMsec() != null) { publisher.maxTime(filterQuery.getMeta().getMaxTimeMsec(), TimeUnit.MILLISECONDS); @@ -2369,8 +2374,11 @@ protected Mono doFindOne(String collectionName, Document query, @Nullable Class entityClass, FindPublisherPreparer preparer) { MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - Document mappedQuery = queryMapper.getMappedObject(query, entity); - Document mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity); + + QueryContext queryContext = queryOperations + .createQueryContext(new BasicQuery(query, fields != null ? fields : new Document())); + Document mappedFields = queryContext.getMappedFields(entity, entityClass, projectionFactory); + Document mappedQuery = queryContext.getMappedQuery(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("findOne using query: %s fields: %s for class: %s in collection: %s", @@ -2420,8 +2428,9 @@ protected Flux doFind(String collectionName, Document query, Document MongoPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - Document mappedFields = queryMapper.getMappedFields(fields, entity); - Document mappedQuery = queryMapper.getMappedObject(query, entity); + QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields)); + Document mappedFields = queryContext.getMappedFields(entity, entityClass, projectionFactory); + Document mappedQuery = queryContext.getMappedQuery(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("find using query: %s fields: %s for class: %s in collection: %s", @@ -2443,8 +2452,9 @@ Flux doFind(String collectionName, Document query, Document fields, Cl MongoPersistentEntity entity = mappingContext.getPersistentEntity(sourceClass); - Document mappedFields = getMappedFieldsObject(fields, entity, targetClass); - Document mappedQuery = queryMapper.getMappedObject(query, entity); + QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields)); + Document mappedFields = queryContext.getMappedFields(entity, targetClass, projectionFactory); + Document mappedQuery = queryContext.getMappedQuery(entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug("find using query: {} fields: {} for class: {} in collection: {}", diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index 07757dc25f..363f167a04 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -208,8 +208,9 @@ void shouldCreateIndexOnAccess() { StepVerifier.create(template.getCollection("indexedSample").listIndexes(Document.class)).expectNextCount(0) .verifyComplete(); - template.findAll(IndexedSample.class) // - .delayElements(Duration.ofMillis(200)) // TODO: check if 4.2.0 server GA still requires this timeout + template.findAll(IndexedSample.class).defaultIfEmpty(new IndexedSample()) // + .delayElements(Duration.ofMillis(500)) // TODO: check if 4.2.0 server GA still requires this timeout + .then() .as(StepVerifier::create) // .verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java index 26eee53bf3..9160105532 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UpdateOperationsUnitTests.java @@ -49,8 +49,9 @@ class UpdateOperationsUnitTests { QueryMapper queryMapper = new QueryMapper(mongoConverter); UpdateMapper updateMapper = new UpdateMapper(mongoConverter); EntityOperations entityOperations = new EntityOperations(mappingContext); + PropertyOperations propertyOperations = new PropertyOperations(mappingContext); - ExtendedQueryOperations queryOperations = new ExtendedQueryOperations(queryMapper, updateMapper, entityOperations, + ExtendedQueryOperations queryOperations = new ExtendedQueryOperations(queryMapper, updateMapper, entityOperations, propertyOperations, MongoClientSettings::getDefaultCodecRegistry); @Test // DATAMONGO-2341 @@ -123,9 +124,9 @@ MongoPersistentEntity entityOf(Class type) { class ExtendedQueryOperations extends QueryOperations { - ExtendedQueryOperations(QueryMapper queryMapper, UpdateMapper updateMapper, EntityOperations entityOperations, + ExtendedQueryOperations(QueryMapper queryMapper, UpdateMapper updateMapper, EntityOperations entityOperations, PropertyOperations propertyOperations, CodecRegistryProvider codecRegistryProvider) { - super(queryMapper, updateMapper, entityOperations, codecRegistryProvider); + super(queryMapper, updateMapper, entityOperations, propertyOperations, codecRegistryProvider); } @NonNull diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java index 75c83049d9..7e7f3c1ed4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java @@ -169,13 +169,13 @@ public void derivedSortForTextScorePropertyWorksCorrectly() { assertThat(result.get(0)).isEqualTo(snipes); } - @Test // DATAMONGO-973 + @Test // DATAMONGO-973, DATAMONGO-2516 public void derivedFinderMethodWithoutFullTextShouldNoCauseTroubleWhenHavingEntityWithTextScoreProperty() { initRepoWithDefaultDocuments(); List result = repo.findByTitle(DROP_ZONE.getTitle()); assertThat(result.get(0)).isEqualTo(DROP_ZONE); - assertThat(result.get(0).score).isEqualTo(0.0F); + assertThat(result.get(0).score).isNull(); } private void initRepoWithDefaultDocuments() { From 00034d899a02bdf26036f4b966d4e50c012df3ab Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 Apr 2020 11:12:19 +0200 Subject: [PATCH 0146/1381] DATAMONGO-2516 - Polishing. Reflect nullability change in TextScore Javadoc. Update documentation. Original pull request: #856. --- .../data/mongodb/core/mapping/TextScore.java | 4 ++- ...oRepositoryTextSearchIntegrationTests.java | 27 ++++++++++--------- src/main/asciidoc/new-features.adoc | 1 + 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java index a21a976eb5..5f1af082ad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java @@ -26,9 +26,11 @@ /** * {@link TextScore} marks the property to be considered as the on server calculated {@literal textScore} when doing * full text search.
      - * NOTE Property will not be written when saving entity. + * NOTE Property will not be written when saving entity and may be {@literal null} if the document is retrieved + * by a regular (i.e. {@literal $text}) query. * * @author Christoph Strobl + * @author Mark Paluch * @since 1.6 */ @ReadOnlyProperty diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java index 7e7f3c1ed4..87488703a5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java @@ -48,7 +48,7 @@ * @author Mark Paluch */ @ExtendWith(MongoTemplateExtension.class) -public class MongoRepositoryTextSearchIntegrationTests { +class MongoRepositoryTextSearchIntegrationTests { private static final FullTextDocument PASSENGER_57 = new FullTextDocument("1", "Passenger 57", "Passenger 57 is an action film that stars Wesley Snipes and Bruce Payne."); @@ -58,24 +58,24 @@ public class MongoRepositoryTextSearchIntegrationTests { "Drop Zone is an action film featuring Wesley Snipes and Gary Busey."); @Template(initialEntitySet = FullTextDocument.class) // - static MongoTestTemplate template; + private static MongoTestTemplate template; - FullTextRepository repo = new MongoRepositoryFactory(this.template).getRepository(FullTextRepository.class); + private FullTextRepository repo = new MongoRepositoryFactory(this.template).getRepository(FullTextRepository.class); @BeforeEach - public void setUp() { + void setUp() { template.indexOps(FullTextDocument.class) .ensureIndex(new TextIndexDefinitionBuilder().onField("title").onField("content").build()); } @AfterEach - public void tearDown() { + void tearDown() { template.flush(); } @Test // DATAMONGO-973 - public void findAllByTextCriteriaShouldReturnMatchingDocuments() { + void findAllByTextCriteriaShouldReturnMatchingDocuments() { initRepoWithDefaultDocuments(); @@ -86,7 +86,7 @@ public void findAllByTextCriteriaShouldReturnMatchingDocuments() { } @Test // DATAMONGO-973 - public void derivedFinderWithTextCriteriaReturnsCorrectResult() { + void derivedFinderWithTextCriteriaReturnsCorrectResult() { initRepoWithDefaultDocuments(); FullTextDocument blade = new FullTextDocument("4", "Blade", @@ -102,7 +102,7 @@ public void derivedFinderWithTextCriteriaReturnsCorrectResult() { } @Test // DATAMONGO-973 - public void findByWithPaginationWorksCorrectlyWhenUsingTextCriteria() { + void findByWithPaginationWorksCorrectlyWhenUsingTextCriteria() { initRepoWithDefaultDocuments(); @@ -116,7 +116,7 @@ public void findByWithPaginationWorksCorrectlyWhenUsingTextCriteria() { } @Test // DATAMONGO-973 - public void findAllByTextCriteriaWithSortWorksCorrectly() { + void findAllByTextCriteriaWithSortWorksCorrectly() { initRepoWithDefaultDocuments(); FullTextDocument snipes = new FullTextDocument("4", "Snipes", "Wesley Trent Snipes is an actor and film producer."); @@ -130,7 +130,7 @@ public void findAllByTextCriteriaWithSortWorksCorrectly() { } @Test // DATAMONGO-973 - public void findByWithSortByScoreViaPageRequestTriggersSortingCorrectly() { + void findByWithSortByScoreViaPageRequestTriggersSortingCorrectly() { initRepoWithDefaultDocuments(); FullTextDocument snipes = new FullTextDocument("4", "Snipes", "Wesley Trent Snipes is an actor and film producer."); @@ -144,7 +144,7 @@ public void findByWithSortByScoreViaPageRequestTriggersSortingCorrectly() { } @Test // DATAMONGO-973 - public void findByWithSortViaPageRequestIgnoresTextScoreWhenSortedByOtherProperty() { + void findByWithSortViaPageRequestIgnoresTextScoreWhenSortedByOtherProperty() { initRepoWithDefaultDocuments(); FullTextDocument snipes = new FullTextDocument("4", "Snipes", "Wesley Trent Snipes is an actor and film producer."); @@ -158,7 +158,7 @@ public void findByWithSortViaPageRequestIgnoresTextScoreWhenSortedByOtherPropert } @Test // DATAMONGO-973 - public void derivedSortForTextScorePropertyWorksCorrectly() { + void derivedSortForTextScorePropertyWorksCorrectly() { initRepoWithDefaultDocuments(); FullTextDocument snipes = new FullTextDocument("4", "Snipes", "Wesley Trent Snipes is an actor and film producer."); @@ -170,10 +170,11 @@ public void derivedSortForTextScorePropertyWorksCorrectly() { } @Test // DATAMONGO-973, DATAMONGO-2516 - public void derivedFinderMethodWithoutFullTextShouldNoCauseTroubleWhenHavingEntityWithTextScoreProperty() { + void derivedFinderMethodWithoutFullTextShouldNoCauseTroubleWhenHavingEntityWithTextScoreProperty() { initRepoWithDefaultDocuments(); List result = repo.findByTitle(DROP_ZONE.getTitle()); + assertThat(result.get(0)).isEqualTo(DROP_ZONE); assertThat(result.get(0).score).isNull(); } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index e6f2a38734..46f953d762 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -11,6 +11,7 @@ * Apply pagination when using GridFS `find(Query)`. * <> via `@Sharded`. * `$merge` and `$addFields` aggregation pipeline stages. +* `@TextScore` is `null` for entities retrieved through non-fulltext queries. [[new-features.2-2-0]] == What's New in Spring Data MongoDB 2.2 From 3a14af54851b8e256bd93124e830281952b67a6a Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 15 Apr 2020 13:47:17 +0200 Subject: [PATCH 0147/1381] DATAMONGO-2513 - Fix Eq aggregation operator comparing collection values. Original pull request: #855. --- .../AbstractAggregationExpression.java | 18 +++++++++++++++--- .../core/aggregation/ComparisonOperators.java | 6 +++--- .../ProjectionOperationUnitTests.java | 9 +++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java index b1f24e6cf1..ad607cbcae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -100,14 +101,14 @@ private Object unpack(Object value, AggregationOperationContext context) { return value; } - protected List append(Object value) { + protected List append(Object value, Expand expandList) { if (this.value instanceof List) { List clone = new ArrayList((List) this.value); - if (value instanceof List) { - clone.addAll((List) value); + if (value instanceof Collection && Expand.EXPAND_VALUES.equals(expandList)) { + clone.addAll((Collection) value); } else { clone.add(value); } @@ -117,6 +118,17 @@ protected List append(Object value) { return Arrays.asList(this.value, value); } + /** + * Expand a nested list of values to single entries or keep the list. + */ + protected enum Expand { + EXPAND_VALUES, KEEP_SOURCE + } + + protected List append(Object value) { + return append(value, Expand.EXPAND_VALUES); + } + @SuppressWarnings("unchecked") protected java.util.Map append(String key, Object value) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java index c39e79f54e..2ce153a0f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java @@ -411,7 +411,7 @@ public Cmp compareTo(AggregationExpression expression) { public Cmp compareToValue(Object value) { Assert.notNull(value, "Value must not be null!"); - return new Cmp(append(value)); + return new Cmp(append(value, Expand.KEEP_SOURCE)); } } @@ -488,7 +488,7 @@ public Eq equalTo(AggregationExpression expression) { public Eq equalToValue(Object value) { Assert.notNull(value, "Value must not be null!"); - return new Eq(append(value)); + return new Eq(append(value, Expand.KEEP_SOURCE)); } } @@ -873,7 +873,7 @@ public Ne notEqualTo(AggregationExpression expression) { public Ne notEqualToValue(Object value) { Assert.notNull(value, "Value must not be null!"); - return new Ne(append(value)); + return new Ne(append(value, Expand.KEEP_SOURCE)); } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index 3a7ca1f5d4..5e7dbbcc04 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -1499,6 +1499,15 @@ public void shouldRenderEqAggregationExpression() { assertThat(agg).isEqualTo(Document.parse("{ $project: { eq250: { $eq: [\"$qty\", 250]} } }")); } + @Test // DATAMONGO-2513 + public void shouldRenderEqAggregationExpressionWithListComparison() { + + Document agg = project().and(ComparisonOperators.valueOf("qty").equalToValue(Arrays.asList(250))).as("eq250") + .toDocument(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg).isEqualTo(Document.parse("{ $project: { eq250: { $eq: [\"$qty\", [250]]} } }")); + } + @Test // DATAMONGO-1536 public void shouldRenderGtAggregationExpression() { From 8cfbd39c7e919c606cd19edf838f048eea8da94f Mon Sep 17 00:00:00 2001 From: Mathieu Ouellet <6408576+mouellet@users.noreply.github.com> Date: Thu, 23 Apr 2020 11:39:06 +0200 Subject: [PATCH 0148/1381] DATAMONGO-2505 - Deferred Database retrieval from ReactiveMongoDatabaseFactory. Change ReactiveMongoDatabaseFactory#getMongoDatabase() methods return Mono to enable access to the subscriber context. Original pull request: #854. --- .../mongodb/ReactiveMongoDatabaseFactory.java | 10 +- .../mongodb/ReactiveMongoDatabaseUtils.java | 12 +- .../mongodb/core/ReactiveMongoOperations.java | 3 +- .../mongodb/core/ReactiveMongoTemplate.java | 50 +++--- .../SimpleReactiveMongoDatabaseFactory.java | 36 +++- .../gridfs/ReactiveGridFsTemplate.java | 162 ++++++++++++++---- .../ReactiveMongoDatabaseUtilsUnitTests.java | 3 +- ...ctiveMongoTransactionManagerUnitTests.java | 5 +- .../DefaultReactiveIndexOperationsTests.java | 6 +- ...faultReactiveIndexOperationsUnitTests.java | 4 +- .../core/ReactiveMongoTemplateIndexTests.java | 37 ++-- ...ReactiveMongoTemplateTransactionTests.java | 5 +- .../core/ReactiveMongoTemplateUnitTests.java | 3 +- ...iveSessionBoundMongoTemplateUnitTests.java | 6 +- ...ReactiveMongoDatabaseFactoryUnitTests.java | 3 +- ...PersistentEntityIndexCreatorUnitTests.java | 3 +- .../mapreduce/ReactiveMapReduceTests.java | 17 +- .../test/util/ReactiveMongoTestTemplate.java | 24 +-- 18 files changed, 260 insertions(+), 129 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java index 05932f7e00..d673fd98ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java @@ -31,6 +31,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet * @since 2.0 */ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { @@ -41,7 +42,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { * @return * @throws DataAccessException */ - MongoDatabase getMongoDatabase() throws DataAccessException; + Mono getMongoDatabase() throws DataAccessException; /** * Obtain a {@link MongoDatabase} instance to access the database with the given name. @@ -50,7 +51,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { * @return * @throws DataAccessException */ - MongoDatabase getMongoDatabase(String dbName) throws DataAccessException; + Mono getMongoDatabase(String dbName) throws DataAccessException; /** * Exposes a shared {@link MongoExceptionTranslator}. @@ -64,10 +65,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { * * @return never {@literal null}. */ - @Override - default CodecRegistry getCodecRegistry() { - return getMongoDatabase().getCodecRegistry(); - } + CodecRegistry getCodecRegistry(); /** * Obtain a {@link Mono} emitting a {@link ClientSession} for given {@link ClientSessionOptions options}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java index 37a5b3d0f6..6138d71a57 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java @@ -41,6 +41,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet * @since 2.2 */ public class ReactiveMongoDatabaseUtils { @@ -142,14 +143,13 @@ private static Mono doGetMongoDatabase(@Nullable String dbName, R .flatMap(synchronizationManager -> { return doGetSession(synchronizationManager, factory, sessionSynchronization) // - .map(it -> getMongoDatabaseOrDefault(dbName, factory.withSession(it))); - }) - .onErrorResume(NoTransactionException.class, - e -> Mono.fromSupplier(() -> getMongoDatabaseOrDefault(dbName, factory))) - .defaultIfEmpty(getMongoDatabaseOrDefault(dbName, factory)); + .flatMap(it -> getMongoDatabaseOrDefault(dbName, factory.withSession(it))); + }) // + .onErrorResume(NoTransactionException.class, e -> getMongoDatabaseOrDefault(dbName, factory)) + .switchIfEmpty(getMongoDatabaseOrDefault(dbName, factory)); } - private static MongoDatabase getMongoDatabaseOrDefault(@Nullable String dbName, + private static Mono getMongoDatabaseOrDefault(@Nullable String dbName, ReactiveMongoDatabaseFactory factory) { return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 1eb5df3d7b..58d1fa1153 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -66,6 +66,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet * @since 2.0 * @see Flux * @see Mono @@ -298,7 +299,7 @@ Mono> createCollection(Class entityClass, * @param collectionName name of the collection. * @return an existing collection or one created on first server interaction. */ - MongoCollection getCollection(String collectionName); + Mono> getCollection(String collectionName); /** * Check to see if a collection with a name indicated by the entity class exists. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index baddbb2b5d..67eec65940 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -156,6 +156,7 @@ * @author Mark Paluch * @author Christoph Strobl * @author Roman Puchkovskiy + * @author Mathieu Ouellet * @since 2.0 */ public class ReactiveMongoTemplate implements ReactiveMongoOperations, ApplicationContextAware { @@ -718,15 +719,11 @@ public Mono> createCollection(String collectionName, * (non-Javadoc) * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#getCollection(java.lang.String) */ - public MongoCollection getCollection(String collectionName) { + public Mono> getCollection(String collectionName) { Assert.notNull(collectionName, "Collection name must not be null!"); - try { - return this.mongoDatabaseFactory.getMongoDatabase().getCollection(collectionName); - } catch (RuntimeException e) { - throw potentiallyConvertRuntimeException(e, exceptionTranslator); - } + return createMono(db -> Mono.just(db.getCollection(collectionName))); } /* @@ -777,7 +774,7 @@ public Flux getCollectionNames() { return createFlux(MongoDatabase::listCollectionNames); } - public MongoDatabase getMongoDatabase() { + public Mono getMongoDatabase() { return mongoDatabaseFactory.getMongoDatabase(); } @@ -2074,24 +2071,25 @@ public Flux> changeStream(@Nullable String database, @N FullDocument fullDocument = ClassUtils.isAssignable(Document.class, targetType) ? FullDocument.DEFAULT : FullDocument.UPDATE_LOOKUP; - MongoDatabase db = StringUtils.hasText(database) ? mongoDatabaseFactory.getMongoDatabase(database) - : getMongoDatabase(); - - ChangeStreamPublisher publisher; - if (StringUtils.hasText(collectionName)) { - publisher = filter.isEmpty() ? db.getCollection(collectionName).watch(Document.class) - : db.getCollection(collectionName).watch(filter, Document.class); + return ReactiveMongoDatabaseUtils.getDatabase(database, mongoDatabaseFactory) // + .map(db -> { + ChangeStreamPublisher publisher; + if (StringUtils.hasText(collectionName)) { + publisher = filter.isEmpty() ? db.getCollection(collectionName).watch(Document.class) + : db.getCollection(collectionName).watch(filter, Document.class); - } else { - publisher = filter.isEmpty() ? db.watch(Document.class) : db.watch(filter, Document.class); - } - - publisher = options.getResumeToken().map(BsonValue::asDocument).map(publisher::resumeAfter).orElse(publisher); - publisher = options.getCollation().map(Collation::toMongoCollation).map(publisher::collation).orElse(publisher); - publisher = options.getResumeBsonTimestamp().map(publisher::startAtOperationTime).orElse(publisher); - publisher = publisher.fullDocument(options.getFullDocumentLookup().orElse(fullDocument)); + } else { + publisher = filter.isEmpty() ? db.watch(Document.class) : db.watch(filter, Document.class); + } - return Flux.from(publisher).map(document -> new ChangeStreamEvent<>(document, targetType, getConverter())); + publisher = options.getResumeToken().map(BsonValue::asDocument).map(publisher::resumeAfter).orElse(publisher); + publisher = options.getCollation().map(Collation::toMongoCollation).map(publisher::collation) + .orElse(publisher); + publisher = options.getResumeBsonTimestamp().map(publisher::startAtOperationTime).orElse(publisher); + return publisher.fullDocument(options.getFullDocumentLookup().orElse(fullDocument)); + }) // + .flatMapMany(publisher -> Flux.from(publisher) + .map(document -> new ChangeStreamEvent<>(document, targetType, getConverter()))); } List prepareFilter(ChangeStreamOptions options) { @@ -2337,7 +2335,7 @@ protected Mono> doCreateCollection(String collectionNa LOGGER.debug("Created collection [{}]", collectionName); } - }).thenReturn(getCollection(collectionName)); + }).then(getCollection(collectionName)); } /** @@ -3350,7 +3348,7 @@ static class ReactiveSessionBoundMongoTemplate extends ReactiveMongoTemplate { * @see org.springframework.data.mongodb.core.ReactiveMongoTemplate#getCollection(java.lang.String) */ @Override - public MongoCollection getCollection(String collectionName) { + public Mono> getCollection(String collectionName) { // native MongoDB objects that offer methods with ClientSession must not be proxied. return delegate.getCollection(collectionName); @@ -3361,7 +3359,7 @@ public MongoCollection getCollection(String collectionName) { * @see org.springframework.data.mongodb.core.ReactiveMongoTemplate#getMongoDatabase() */ @Override - public MongoDatabase getMongoDatabase() { + public Mono getMongoDatabase() { // native MongoDB objects that offer methods with ClientSession must not be proxied. return delegate.getMongoDatabase(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java index 4d91dcd356..545357ea9a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java @@ -18,6 +18,7 @@ import lombok.Value; import reactor.core.publisher.Mono; +import org.bson.codecs.configuration.CodecRegistry; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.dao.DataAccessException; @@ -41,6 +42,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet * @since 2.0 */ public class SimpleReactiveMongoDatabaseFactory implements DisposableBean, ReactiveMongoDatabaseFactory { @@ -99,7 +101,7 @@ public void setWriteConcern(WriteConcern writeConcern) { * (non-Javadoc) * @see org.springframework.data.mongodb.ReactiveMongoDbFactory#getMongoDatabase() */ - public MongoDatabase getMongoDatabase() throws DataAccessException { + public Mono getMongoDatabase() throws DataAccessException { return getMongoDatabase(databaseName); } @@ -107,12 +109,12 @@ public MongoDatabase getMongoDatabase() throws DataAccessException { * (non-Javadoc) * @see org.springframework.data.mongodb.ReactiveMongoDbFactory#getMongoDatabase(java.lang.String) */ - public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { + public Mono getMongoDatabase(String dbName) throws DataAccessException { Assert.hasText(dbName, "Database name must not be empty."); - MongoDatabase db = mongo.getDatabase(dbName); - return writeConcern != null ? db.withWriteConcern(writeConcern) : db; + return Mono.just(mongo.getDatabase(dbName)) + .map(db -> writeConcern != null ? db.withWriteConcern(writeConcern) : db); } /** @@ -135,6 +137,15 @@ public PersistenceExceptionTranslator getExceptionTranslator() { return this.exceptionTranslator; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getCodecRegistry() + */ + @Override + public CodecRegistry getCodecRegistry() { + return this.mongo.getDatabase(databaseName).getCodecRegistry(); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.ReactiveMongoDbFactory#getSession(com.mongodb.ClientSessionOptions) @@ -171,8 +182,8 @@ static class ClientSessionBoundMongoDbFactory implements ReactiveMongoDatabaseFa * @see org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getMongoDatabase() */ @Override - public MongoDatabase getMongoDatabase() throws DataAccessException { - return decorateDatabase(delegate.getMongoDatabase()); + public Mono getMongoDatabase() throws DataAccessException { + return delegate.getMongoDatabase().map(this::decorateDatabase); } /* @@ -180,8 +191,8 @@ public MongoDatabase getMongoDatabase() throws DataAccessException { * @see org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getMongoDatabase(java.lang.String) */ @Override - public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { - return decorateDatabase(delegate.getMongoDatabase(dbName)); + public Mono getMongoDatabase(String dbName) throws DataAccessException { + return delegate.getMongoDatabase(dbName).map(this::decorateDatabase); } /* @@ -193,6 +204,15 @@ public PersistenceExceptionTranslator getExceptionTranslator() { return delegate.getExceptionTranslator(); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getCodecRegistry() + */ + @Override + public CodecRegistry getCodecRegistry() { + return delegate.getCodecRegistry(); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getSession(com.mongodb.ClientSessionOptions) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index 524de7b9b2..ceea4a3e32 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -18,9 +18,13 @@ import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.gridfs.GridFsCriteria.*; +import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.nio.ByteBuffer; + +import org.bson.BsonValue; import org.bson.Document; import org.bson.types.ObjectId; import org.reactivestreams.Publisher; @@ -39,7 +43,6 @@ import com.mongodb.client.gridfs.model.GridFSFile; import com.mongodb.client.gridfs.model.GridFSUploadOptions; -import com.mongodb.reactivestreams.client.MongoDatabase; import com.mongodb.reactivestreams.client.gridfs.GridFSBucket; import com.mongodb.reactivestreams.client.gridfs.GridFSBuckets; import com.mongodb.reactivestreams.client.gridfs.GridFSFindPublisher; @@ -53,6 +56,7 @@ * @author Nick Stolwijk * @author Denis Zavedeev * @author Christoph Strobl + * @author Mathieu Ouellet * @since 2.2 */ public class ReactiveGridFsTemplate extends GridFsOperationsSupport implements ReactiveGridFsOperations { @@ -130,18 +134,15 @@ public Mono store(GridFsObject> upload) { uploadOptions.chunkSizeBytes(upload.getOptions().getChunkSize()); } - if (upload.getFileId() == null) { - GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher(upload.getFilename(), - Flux.from(upload.getContent()).map(DataBuffer::asByteBuffer), uploadOptions); - - return (Mono) Mono.from(publisher); + String filename = upload.getFilename(); + Flux source = Flux.from(upload.getContent()).map(DataBuffer::asByteBuffer); + T fileId = upload.getFileId(); + if (fileId == null) { + return (Mono) createMono(new AutoIdCreatingUploadCallback(filename, source, uploadOptions)); } - GridFSUploadPublisher publisher = getGridFs().uploadFromPublisher( - BsonUtils.simpleToBsonValue(upload.getFileId()), upload.getFilename(), - Flux.from(upload.getContent()).map(DataBuffer::asByteBuffer), uploadOptions); - - return Mono.from(publisher).then(Mono.just(upload.getFileId())); + UploadCallback callback = new UploadCallback(BsonUtils.simpleToBsonValue(fileId), filename, source, uploadOptions); + return createMono(callback).then(Mono.just(fileId)); } /* @@ -150,7 +151,11 @@ public Mono store(GridFsObject> upload) { */ @Override public Flux find(Query query) { - return Flux.from(prepareQuery(query)); + + Document queryObject = getMappedQuery(query.getQueryObject()); + Document sortObject = getMappedQuery(query.getSortObject()); + + return createFlux(new FindCallback(query, queryObject, sortObject)); } /* @@ -160,7 +165,10 @@ public Flux find(Query query) { @Override public Mono findOne(Query query) { - return Flux.from(prepareQuery(query).limit(2)) // + Document queryObject = getMappedQuery(query.getQueryObject()); + Document sortObject = getMappedQuery(query.getSortObject()); + + return createFlux(new FindLimitCallback(query, queryObject, sortObject, 2)) // .collectList() // .flatMap(it -> { if (it.isEmpty()) { @@ -182,7 +190,11 @@ public Mono findOne(Query query) { */ @Override public Mono findFirst(Query query) { - return Flux.from(prepareQuery(query).limit(1)).next(); + + Document queryObject = getMappedQuery(query.getQueryObject()); + Document sortObject = getMappedQuery(query.getSortObject()); + + return createFlux(new FindLimitCallback(query, queryObject, sortObject, 1)).next(); } /* @@ -191,7 +203,7 @@ public Mono findFirst(Query query) { */ @Override public Mono delete(Query query) { - return find(query).flatMap(it -> getGridFs().delete(it.getId())).then(); + return find(query).flatMap(it -> createMono(new DeleteCallback(it.getId()))).then(); } /* @@ -216,9 +228,8 @@ public Mono getResource(GridFSFile file) { Assert.notNull(file, "GridFSFile must not be null!"); - return Mono.fromSupplier(() -> { - return new ReactiveGridFsResource(file, getGridFs().downloadToPublisher(file.getId()), dataBufferFactory); - }); + return this.doGetBucket() + .map(it -> new ReactiveGridFsResource(file, it.downloadToPublisher(file.getId()), dataBufferFactory)); } /* @@ -243,34 +254,117 @@ public Flux getResources(String locationPattern) { return getResource(locationPattern).flux(); } - protected GridFSFindPublisher prepareQuery(Query query) { + /** + * Create a reusable Mono for a {@link ReactiveBucketCallback}. It's up to the developer to choose to obtain a new + * {@link Flux} or to reuse the {@link Flux}. + * + * @param callback must not be {@literal null} + * @return a {@link Mono} wrapping the {@link ReactiveBucketCallback}. + */ + public Mono createMono(ReactiveBucketCallback callback) { - Assert.notNull(query, "Query must not be null!"); + Assert.notNull(callback, "ReactiveBucketCallback must not be null!"); - Document queryObject = getMappedQuery(query.getQueryObject()); - Document sortObject = getMappedQuery(query.getSortObject()); + return Mono.defer(this::doGetBucket).flatMap(bucket -> Mono.from(callback.doInBucket(bucket))); + } - GridFSFindPublisher publisherToUse = getGridFs().find(queryObject).sort(sortObject); + /** + * Create a reusable Flux for a {@link ReactiveBucketCallback}. It's up to the developer to choose to obtain a new + * {@link Flux} or to reuse the {@link Flux}. + * + * @param callback must not be {@literal null} + * @return a {@link Flux} wrapping the {@link ReactiveBucketCallback}. + */ + public Flux createFlux(ReactiveBucketCallback callback) { - if (query.getLimit() > 0) { - publisherToUse = publisherToUse.limit(query.getLimit()); + Assert.notNull(callback, "ReactiveBucketCallback must not be null!"); + + return Mono.defer(this::doGetBucket).flatMapMany(callback::doInBucket); + } + + protected Mono doGetBucket() { + return dbFactory.getMongoDatabase() + .map(db -> bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket)); + } + + interface ReactiveBucketCallback { + Publisher doInBucket(GridFSBucket bucket); + } + + @RequiredArgsConstructor + private static class FindCallback implements ReactiveBucketCallback { + + private final Query query; + private final Document queryObject; + private final Document sortObject; + + public GridFSFindPublisher doInBucket(GridFSBucket bucket) { + GridFSFindPublisher findPublisher = bucket.find(queryObject).sort(sortObject); + if (query.getLimit() > 0) { + findPublisher = findPublisher.limit(query.getLimit()); + } + if (query.getSkip() > 0) { + findPublisher = findPublisher.skip(Math.toIntExact(query.getSkip())); + } + Integer cursorBatchSize = query.getMeta().getCursorBatchSize(); + if (cursorBatchSize != null) { + findPublisher = findPublisher.batchSize(cursorBatchSize); + } + return findPublisher; + } + } + + private static class FindLimitCallback extends FindCallback { + + private final int limit; + + public FindLimitCallback(Query query, Document queryObject, Document sortObject, int limit) { + super(query, queryObject, sortObject); + this.limit = limit; } - if (query.getSkip() > 0) { - publisherToUse = publisherToUse.skip(Math.toIntExact(query.getSkip())); + @Override + public GridFSFindPublisher doInBucket(GridFSBucket bucket) { + return super.doInBucket(bucket).limit(limit); } + } + + @RequiredArgsConstructor + private static class UploadCallback implements ReactiveBucketCallback { - Integer cursorBatchSize = query.getMeta().getCursorBatchSize(); - if (cursorBatchSize != null) { - publisherToUse = publisherToUse.batchSize(cursorBatchSize); + private final BsonValue fileId; + private final String filename; + private final Publisher source; + private final GridFSUploadOptions uploadOptions; + + @Override + public GridFSUploadPublisher doInBucket(GridFSBucket bucket) { + return bucket.uploadFromPublisher(fileId, filename, source, uploadOptions); } + } + + @RequiredArgsConstructor + private static class AutoIdCreatingUploadCallback implements ReactiveBucketCallback { - return publisherToUse; + private final String filename; + private final Publisher source; + private final GridFSUploadOptions uploadOptions; + + @Override + public GridFSUploadPublisher doInBucket(GridFSBucket bucket) { + return bucket.uploadFromPublisher(filename, source, uploadOptions); + } } - protected GridFSBucket getGridFs() { + @RequiredArgsConstructor + private static class DeleteCallback implements ReactiveBucketCallback { + + private final BsonValue id; - MongoDatabase db = dbFactory.getMongoDatabase(); - return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket); + @Override + public Publisher doInBucket(GridFSBucket bucket) { + return bucket.delete(id); + } } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java index f05e1c6769..39b9c4a90d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java @@ -40,6 +40,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet */ @ExtendWith(MockitoExtension.class) class ReactiveMongoDatabaseUtilsUnitTests { @@ -90,7 +91,7 @@ void isTransactionActiveShouldLookupTxForActiveTransactionSynchronizationViaTxMa @Test // DATAMONGO-2265 void shouldNotStartSessionWhenNoTransactionOngoing() { - when(databaseFactory.getMongoDatabase()).thenReturn(db); + when(databaseFactory.getMongoDatabase()).thenReturn(Mono.just(db)); ReactiveMongoDatabaseUtils.getDatabase(databaseFactory, SessionSynchronization.ON_ACTUAL_TRANSACTION) // .as(StepVerifier::create) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java index d04db25297..8563d56a87 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoTransactionManagerUnitTests.java @@ -40,6 +40,7 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet */ @ExtendWith(MockitoExtension.class) class ReactiveMongoTransactionManagerUnitTests { @@ -56,7 +57,7 @@ class ReactiveMongoTransactionManagerUnitTests { void setUp() { when(databaseFactory.getSession(any())).thenReturn(Mono.just(session), Mono.just(session2)); when(databaseFactory.withSession(session)).thenReturn(databaseFactory); - when(databaseFactory.getMongoDatabase()).thenReturn(db); + when(databaseFactory.getMongoDatabase()).thenReturn(Mono.just(db)); when(session.getServerSession()).thenReturn(serverSession); } @@ -181,7 +182,7 @@ void suspendTransactionWhilePropagationNotSupported() { void suspendTransactionWhilePropagationRequiresNew() { when(databaseFactory.withSession(session2)).thenReturn(databaseFactory2); - when(databaseFactory2.getMongoDatabase()).thenReturn(db2); + when(databaseFactory2.getMongoDatabase()).thenReturn(Mono.just(db2)); when(session2.getServerSession()).thenReturn(serverSession); ReactiveMongoTransactionManager txManager = new ReactiveMongoTransactionManager(databaseFactory); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index 4fe2888be7..7c10414833 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -44,6 +44,7 @@ /** * @author Christoph Strobl * @author Mark Paluch + * @author Mathieu Ouellet */ @ExtendWith(MongoTemplateExtension.class) public class DefaultReactiveIndexOperationsTests { @@ -53,13 +54,14 @@ public class DefaultReactiveIndexOperationsTests { String collectionName = template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - MongoCollection collection = template.getCollection(collectionName); DefaultReactiveIndexOperations indexOps = new DefaultReactiveIndexOperations(template, collectionName, new QueryMapper(template.getConverter())); @BeforeEach public void setUp() { - StepVerifier.create(this.collection.dropIndexes()).verifyComplete(); + template.getCollection(collectionName).flatMapMany(MongoCollection::dropIndexes) // + .as(StepVerifier::create) // + .verifyComplete(); } @Test // DATAMONGO-1518 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java index 2121f6f305..e358689d5a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.*; import lombok.Data; +import reactor.core.publisher.Mono; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -45,6 +46,7 @@ /** * @author Christoph Strobl + * @author Mathieu Ouellet */ @ExtendWith(MockitoExtension.class) public class DefaultReactiveIndexOperationsUnitTests { @@ -63,7 +65,7 @@ public class DefaultReactiveIndexOperationsUnitTests { @BeforeEach void setUp() { - when(factory.getMongoDatabase()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(Mono.just(db)); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(), any(Class.class))).thenReturn(collection); when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn(publisher); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index 363f167a04..636dd05b19 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -48,14 +48,15 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import com.mongodb.client.model.IndexOptions; -import com.mongodb.reactivestreams.client.ListIndexesPublisher; import com.mongodb.reactivestreams.client.MongoClient; +import com.mongodb.reactivestreams.client.MongoCollection; /** * Integration test for index creation via {@link ReactiveMongoTemplate}. * * @author Mark Paluch * @author Christoph Strobl + * @author Mathieu Ouellet */ @ExtendWith(MongoClientExtension.class) public class ReactiveMongoTemplateIndexTests { @@ -73,10 +74,9 @@ void setUp() { mappingContext.setAutoIndexCreation(true); template = new ReactiveMongoTemplate(factory, new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)); - - MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "person", client); - MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "indexfail", client); - MongoTestUtils.dropCollectionNow(template.getMongoDatabase().getName(), "indexedSample", client); + MongoTestUtils.dropCollectionNow("reactive-template-index-tests", "person", client); + MongoTestUtils.dropCollectionNow("reactive-template-index-tests", "indexfail", client); + MongoTestUtils.dropCollectionNow("reactive-template-index-tests", "indexedSample", client); } @AfterEach @@ -99,7 +99,8 @@ void testEnsureIndexShouldCreateIndex() { .expectNextCount(1) // .verifyComplete(); - Flux.from(template.getCollection(template.getCollectionName(Person.class)).listIndexes()).collectList() // + template.getCollection(template.getCollectionName(Person.class)).flatMapMany(MongoCollection::listIndexes) + .collectList() // .as(StepVerifier::create) // .consumeNextWith(indexInfo -> { @@ -161,16 +162,15 @@ void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { .as(StepVerifier::create) // .verifyComplete(); - Flux.from(factory.getMongoDatabase().getCollection(template.getCollectionName(Person.class)) - .createIndex(new Document("age", -1), new IndexOptions().unique(true).sparse(true))) // + factory.getMongoDatabase() // + .flatMapMany(db -> db.getCollection(template.getCollectionName(Person.class)) + .createIndex(new Document("age", -1), new IndexOptions().unique(true).sparse(true))) .as(StepVerifier::create) // .expectNextCount(1) // .verifyComplete(); - ListIndexesPublisher listIndexesPublisher = template - .getCollection(template.getCollectionName(Person.class)).listIndexes(); - - Flux.from(listIndexesPublisher).collectList() // + template.getCollection(template.getCollectionName(Person.class)).flatMapMany(MongoCollection::listIndexes) + .collectList() // .as(StepVerifier::create) // .consumeNextWith(indexInfos -> { @@ -205,7 +205,9 @@ void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { @RepeatFailedTest(3) void shouldCreateIndexOnAccess() { - StepVerifier.create(template.getCollection("indexedSample").listIndexes(Document.class)).expectNextCount(0) + template.getCollection("indexedSample").flatMapMany(it -> it.listIndexes(Document.class)) // + .as(StepVerifier::create) // + .expectNextCount(0) // .verifyComplete(); template.findAll(IndexedSample.class).defaultIfEmpty(new IndexedSample()) // @@ -214,7 +216,9 @@ void shouldCreateIndexOnAccess() { .as(StepVerifier::create) // .verifyComplete(); - StepVerifier.create(template.getCollection("indexedSample").listIndexes(Document.class)).expectNextCount(2) + template.getCollection("indexedSample").flatMapMany(it -> it.listIndexes(Document.class)) // + .as(StepVerifier::create) // + .expectNextCount(2) // .verifyComplete(); } @@ -222,8 +226,9 @@ void shouldCreateIndexOnAccess() { @RepeatFailedTest(3) void indexCreationShouldFail() throws InterruptedException { - Flux.from(factory.getMongoDatabase().getCollection("indexfail") // - .createIndex(new Document("field", 1), new IndexOptions().name("foo").unique(true).sparse(true))) + factory.getMongoDatabase() // + .flatMapMany(db -> db.getCollection("indexfail") // + .createIndex(new Document("field", 1), new IndexOptions().name("foo").unique(true).sparse(true))) .as(StepVerifier::create) // .expectNextCount(1) // .verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java index a92675dad1..86ba2bb645 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java @@ -47,6 +47,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Mathieu Ouellet * @currentRead The Core - Peter V. Brett */ @ExtendWith(MongoClientExtension.class) @@ -186,10 +187,10 @@ public void inTransactionCommitsProvidedTransactionalSession() { public void changesNotVisibleOutsideTransaction() { template.inTransaction().execute(action -> { - return action.remove(ID_QUERY, Document.class, COLLECTION_NAME).flatMap(val -> { + return action.remove(ID_QUERY, Document.class, COLLECTION_NAME).flatMapMany(val -> { // once we use the collection directly we're no longer participating in the tx - return Mono.from(template.getCollection(COLLECTION_NAME).find(ID_QUERY.getQueryObject())); + return template.getCollection(COLLECTION_NAME).flatMapMany(it -> it.find(ID_QUERY.getQueryObject())); }); }).as(StepVerifier::create).expectNext(DOCUMENT).verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 506a4e9e21..1dac146e1d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -116,6 +116,7 @@ * @author Mark Paluch * @author Christoph Strobl * @author Roman Puchkovskiy + * @author Mathieu Ouellet */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -146,7 +147,7 @@ void beforeEach() { when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); - when(factory.getMongoDatabase()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(Mono.just(db)); when(db.getCollection(any())).thenReturn(collection); when(db.getCollection(any(), any())).thenReturn(collection); when(db.runCommand(any(), any(Class.class))).thenReturn(runCommandPublisher); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java index 183772b436..e8e3966d74 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java @@ -69,6 +69,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Mathieu Ouellet */ @SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.Silent.class) @@ -302,12 +303,13 @@ public void upsertShouldUseProxiedCollection() { @Test // DATAMONGO-1880 public void getCollectionShouldShouldJustReturnTheCollection/*No ClientSession binding*/() { - assertThat(template.getCollection(COLLECTION_NAME)).isNotInstanceOf(Proxy.class); + assertThat(template.getCollection(COLLECTION_NAME).block()).isNotInstanceOf(Proxy.class) + .isInstanceOf(MongoCollection.class); } @Test // DATAMONGO-1880 public void getDbShouldJustReturnTheDatabase/*No ClientSession binding*/() { - assertThat(template.getMongoDatabase()).isNotInstanceOf(Proxy.class); + assertThat(template.getMongoDatabase().block()).isNotInstanceOf(Proxy.class).isInstanceOf(MongoDatabase.class); } @Test // DATAMONGO-1880 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java index feaa9890cf..ff9aca1d0c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactoryUnitTests.java @@ -38,6 +38,7 @@ * Unit tests for {@link SimpleReactiveMongoDatabaseFactory}. * * @author Mark Paluch + * @author Mathieu Ouellet */ @ExtendWith(MockitoExtension.class) class SimpleReactiveMongoDatabaseFactoryUnitTests { @@ -54,7 +55,7 @@ void cascadedWithSessionUsesRootFactory() { ReactiveMongoDatabaseFactory factory = new SimpleReactiveMongoDatabaseFactory(mongoClient, "foo"); ReactiveMongoDatabaseFactory wrapped = factory.withSession(clientSession).withSession(clientSession); - InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase()); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase().block()); Object singletonTarget = AopProxyUtils .getSingletonTarget(ReflectionTestUtils.getField(invocationHandler, "advised")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java index 1a4e12b29e..71c52002cc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java @@ -50,6 +50,7 @@ * Unit tests for {@link ReactiveMongoPersistentEntityIndexCreator}. * * @author Mark Paluch + * @author Mathieu Ouellet */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -70,7 +71,7 @@ public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { void setUp() { when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); - when(factory.getMongoDatabase()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(Mono.just(db)); when(db.getCollection(any(), any(Class.class))).thenReturn(collection); indexOperations = new ReactiveMongoTemplate(factory).indexOps("foo"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java index 8f02df5d0b..c89bc7eb44 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java @@ -40,10 +40,12 @@ import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoCollection; +import com.mongodb.reactivestreams.client.MongoDatabase; /** * @author Christoph Strobl * @author Mark Paluch + * @author Mathieu Ouellet * @currentRead Beyond the Shadows - Brent Weeks */ @RunWith(SpringRunner.class) @@ -62,7 +64,8 @@ public void setUp() { template.dropCollection(ValueObject.class) // .mergeWith(template.dropCollection("jmr1")) // .mergeWith(template.dropCollection("jmr1_out")) // - .mergeWith(Mono.from(factory.getMongoDatabase("reactive-jrm1-out-db").drop()).then()).as(StepVerifier::create) // + .mergeWith(factory.getMongoDatabase("reactive-jrm1-out-db").map(MongoDatabase::drop).then()) // + .as(StepVerifier::create) // .verifyComplete(); } @@ -144,7 +147,7 @@ public void mapReduceWithOutputDatabase() { MapReduceOptions.options().outputDatabase("reactive-jrm1-out-db").outputCollection("jmr1_out")) .as(StepVerifier::create).expectNextCount(4).verifyComplete(); - Flux.from(factory.getMongoDatabase("reactive-jrm1-out-db").listCollectionNames()).buffer(10) + factory.getMongoDatabase("reactive-jrm1-out-db").flatMapMany(MongoDatabase::listCollectionNames).buffer(10) .map(list -> list.contains("jmr1_out")).as(StepVerifier::create).expectNext(true).verifyComplete(); } @@ -190,11 +193,11 @@ public void throwsExceptionWhenTryingToLoadFunctionsFromDisk() { private void createMapReduceData() { - MongoCollection collection = factory.getMongoDatabase().getCollection("jmr1", Document.class); - - StepVerifier - .create(collection.insertMany(Arrays.asList(new Document("x", Arrays.asList("a", "b")), - new Document("x", Arrays.asList("b", "c")), new Document("x", Arrays.asList("c", "d"))))) + factory.getMongoDatabase() + .flatMapMany(db -> db.getCollection("jmr1", Document.class) + .insertMany(Arrays.asList(new Document("x", Arrays.asList("a", "b")), + new Document("x", Arrays.asList("b", "c")), new Document("x", Arrays.asList("c", "d"))))) + .as(StepVerifier::create) // .expectNextCount(1) // .verifyComplete(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java index 290b78c2d5..05240b20d5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java @@ -31,11 +31,14 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import com.mongodb.reactivestreams.client.MongoClient; +import com.mongodb.reactivestreams.client.MongoCollection; +import com.mongodb.reactivestreams.client.MongoDatabase; /** * A {@link ReactiveMongoTemplate} with configuration hooks and extension suitable for tests. * * @author Christoph Strobl + * @author Mathieu Ouellet * @since 3.0 */ public class ReactiveMongoTestTemplate extends ReactiveMongoTemplate { @@ -96,7 +99,7 @@ public Mono flush() { } public Mono flushDatabase() { - return flush(getMongoDatabase().listCollectionNames()); + return flush(getMongoDatabase().flatMapMany(MongoDatabase::listCollectionNames)); } public Mono flush(Class... entities) { @@ -110,8 +113,8 @@ public Mono flush(String... collections) { public Mono flush(Publisher collectionNames) { return Flux.from(collectionNames) - .flatMap(collection -> Mono.from(getCollection(collection).deleteMany(new Document())).then() - .onErrorResume(it -> Mono.from(getCollection(collection).drop()).then())) + .flatMap(collection -> getCollection(collection).flatMapMany(it -> it.deleteMany(new Document())).then() + .onErrorResume(it -> getCollection(collection).flatMapMany(MongoCollection::drop).then())) .then(); } @@ -130,18 +133,15 @@ public Mono flush(Object... objects) { } public Mono dropDatabase() { - return Mono.from(getMongoDatabase().drop()).then(); + return getMongoDatabase().map(MongoDatabase::drop).then(); } - public void dropIndexes(String... collections) { - for (String collection : collections) { - getCollection(collection).dropIndexes(); - } + public Mono dropIndexes(String... collections) { + return Flux.fromArray(collections).flatMap(it -> getCollection(it).map(MongoCollection::dropIndexes).then()).then(); } - public void dropIndexes(Class... entities) { - for (Class entity : entities) { - getCollection(getCollectionName(entity)).dropIndexes(); - } + public Mono dropIndexes(Class... entities) { + return Flux.fromArray(entities) + .flatMap(it -> getCollection(getCollectionName(it)).map(MongoCollection::dropIndexes).then()).then(); } } From 318d5527971547ef770d62aece3c7a19d5e61538 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 23 Apr 2020 12:02:03 +0200 Subject: [PATCH 0149/1381] DATAMONGO-2505 - Polishing. Simplify operators. Remove Lombok usage from newly introduced code. Update reference documentation. Reformat code. Original pull request: #854. --- .../SimpleReactiveMongoDatabaseFactory.java | 8 ++- .../gridfs/ReactiveGridFsTemplate.java | 68 ++++++++++++++----- src/main/asciidoc/upgrading.adoc | 9 ++- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java index 545357ea9a..4eedce82a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java @@ -113,8 +113,12 @@ public Mono getMongoDatabase(String dbName) throws DataAccessExce Assert.hasText(dbName, "Database name must not be empty."); - return Mono.just(mongo.getDatabase(dbName)) - .map(db -> writeConcern != null ? db.withWriteConcern(writeConcern) : db); + return Mono.fromSupplier(() -> { + + MongoDatabase db = mongo.getDatabase(dbName); + + return writeConcern != null ? db.withWriteConcern(writeConcern) : db; + }); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index ceea4a3e32..16540e1a3d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -18,7 +18,6 @@ import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.gridfs.GridFsCriteria.*; -import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -28,6 +27,7 @@ import org.bson.Document; import org.bson.types.ObjectId; import org.reactivestreams.Publisher; + import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory; @@ -137,12 +137,13 @@ public Mono store(GridFsObject> upload) { String filename = upload.getFilename(); Flux source = Flux.from(upload.getContent()).map(DataBuffer::asByteBuffer); T fileId = upload.getFileId(); + if (fileId == null) { return (Mono) createMono(new AutoIdCreatingUploadCallback(filename, source, uploadOptions)); } UploadCallback callback = new UploadCallback(BsonUtils.simpleToBsonValue(fileId), filename, source, uploadOptions); - return createMono(callback).then(Mono.just(fileId)); + return createMono(callback).thenReturn(fileId); } /* @@ -170,17 +171,17 @@ public Mono findOne(Query query) { return createFlux(new FindLimitCallback(query, queryObject, sortObject, 2)) // .collectList() // - .flatMap(it -> { - if (it.isEmpty()) { - return Mono.empty(); + .handle((files, sink) -> { + + if (files.size() == 1) { + sink.next(files.get(0)); + return; } - if (it.size() > 1) { - return Mono.error(new IncorrectResultSizeDataAccessException( + if (files.size() > 1) { + sink.error(new IncorrectResultSizeDataAccessException( "Query " + SerializationUtils.serializeToJsonSafely(query) + " returned non unique result.", 1)); } - - return Mono.just(it.get(0)); }); } @@ -228,7 +229,7 @@ public Mono getResource(GridFSFile file) { Assert.notNull(file, "GridFSFile must not be null!"); - return this.doGetBucket() + return doGetBucket() .map(it -> new ReactiveGridFsResource(file, it.downloadToPublisher(file.getId()), dataBufferFactory)); } @@ -265,7 +266,7 @@ public Mono createMono(ReactiveBucketCallback callback) { Assert.notNull(callback, "ReactiveBucketCallback must not be null!"); - return Mono.defer(this::doGetBucket).flatMap(bucket -> Mono.from(callback.doInBucket(bucket))); + return doGetBucket().flatMap(bucket -> Mono.from(callback.doInBucket(bucket))); } /** @@ -279,7 +280,7 @@ public Flux createFlux(ReactiveBucketCallback callback) { Assert.notNull(callback, "ReactiveBucketCallback must not be null!"); - return Mono.defer(this::doGetBucket).flatMapMany(callback::doInBucket); + return doGetBucket().flatMapMany(callback::doInBucket); } protected Mono doGetBucket() { @@ -287,29 +288,45 @@ protected Mono doGetBucket() { .map(db -> bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket)); } + /** + * @param + * @author Mathieu Ouellet + * @since 3.0 + */ interface ReactiveBucketCallback { Publisher doInBucket(GridFSBucket bucket); } - @RequiredArgsConstructor private static class FindCallback implements ReactiveBucketCallback { private final Query query; private final Document queryObject; private final Document sortObject; + public FindCallback(Query query, Document queryObject, Document sortObject) { + + this.query = query; + this.queryObject = queryObject; + this.sortObject = sortObject; + } + public GridFSFindPublisher doInBucket(GridFSBucket bucket) { + GridFSFindPublisher findPublisher = bucket.find(queryObject).sort(sortObject); + if (query.getLimit() > 0) { findPublisher = findPublisher.limit(query.getLimit()); } + if (query.getSkip() > 0) { findPublisher = findPublisher.skip(Math.toIntExact(query.getSkip())); } + Integer cursorBatchSize = query.getMeta().getCursorBatchSize(); if (cursorBatchSize != null) { findPublisher = findPublisher.batchSize(cursorBatchSize); } + return findPublisher; } } @@ -319,6 +336,7 @@ private static class FindLimitCallback extends FindCallback { private final int limit; public FindLimitCallback(Query query, Document queryObject, Document sortObject, int limit) { + super(query, queryObject, sortObject); this.limit = limit; } @@ -329,7 +347,6 @@ public GridFSFindPublisher doInBucket(GridFSBucket bucket) { } } - @RequiredArgsConstructor private static class UploadCallback implements ReactiveBucketCallback { private final BsonValue fileId; @@ -337,30 +354,49 @@ private static class UploadCallback implements ReactiveBucketCallback { private final Publisher source; private final GridFSUploadOptions uploadOptions; + public UploadCallback(BsonValue fileId, String filename, Publisher source, + GridFSUploadOptions uploadOptions) { + + this.fileId = fileId; + this.filename = filename; + this.source = source; + this.uploadOptions = uploadOptions; + } + @Override public GridFSUploadPublisher doInBucket(GridFSBucket bucket) { return bucket.uploadFromPublisher(fileId, filename, source, uploadOptions); } } - @RequiredArgsConstructor private static class AutoIdCreatingUploadCallback implements ReactiveBucketCallback { private final String filename; private final Publisher source; private final GridFSUploadOptions uploadOptions; + public AutoIdCreatingUploadCallback(String filename, Publisher source, + GridFSUploadOptions uploadOptions) { + + this.filename = filename; + this.source = source; + this.uploadOptions = uploadOptions; + } + @Override public GridFSUploadPublisher doInBucket(GridFSBucket bucket) { return bucket.uploadFromPublisher(filename, source, uploadOptions); } } - @RequiredArgsConstructor private static class DeleteCallback implements ReactiveBucketCallback { private final BsonValue id; + public DeleteCallback(BsonValue id) { + this.id = id; + } + @Override public Publisher doInBucket(GridFSBucket bucket) { return bucket.delete(id); diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index c89376607a..df1bcb092d 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -3,7 +3,8 @@ Spring Data MongoDB 3.x requires the MongoDB Java Driver 4.x. + The 4.0 MongoDB Java Driver does no longer support certain features that have already been deprecated in one of the last minor versions. -Some of the changes affect the initial setup configuration as well as compile/runtime features. We summarized the most typical changes one might encounter. +Some of the changes affect the initial setup configuration as well as compile/runtime features. +We summarized the most typical changes one might encounter. == Dependency Changes @@ -216,3 +217,9 @@ public class Config extends AbstractMongoClientConfiguration { } ---- ==== + +=== Deferred MongoDatabase lookup in `ReactiveMongoDatabaseFactory` + +`ReactiveMongoDatabaseFactory` now returns `Mono` instead of `MongoDatabase` to allow access to the Reactor Subscriber context to enable context-specific routing functionality. + +This change affects `ReactiveMongoTemplate.getMongoDatabase()` and `ReactiveMongoTemplate.getCollection()` so both methods must follow deferred retrieval. From 3ab679bcc7d75ef06b16a06416c2c2a1d5e04e7d Mon Sep 17 00:00:00 2001 From: ddebray Date: Wed, 1 Apr 2020 12:32:02 +0200 Subject: [PATCH 0150/1381] DATAMONGO-2504 - Add hashCode and equals to TextCriteria and Term. Original pull request: #848. --- .../data/mongodb/core/query/Term.java | 16 ++++++++++++++++ .../data/mongodb/core/query/TextCriteria.java | 18 ++++++++++++++++++ .../core/query/TextCriteriaUnitTests.java | 7 +++++++ 3 files changed, 41 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java index ed51e4b400..379445a84c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.query; +import java.util.Objects; import org.springframework.lang.Nullable; /** @@ -102,4 +103,19 @@ protected String quotePhrase(String raw) { protected String negateRaw(String raw) { return "-" + raw; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Term)) return false; + Term term = (Term) o; + return negated == term.negated && + type == term.type && + Objects.equals(raw, term.raw); + } + + @Override + public int hashCode() { + return Objects.hash(type, raw, negated); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java index 66aca4cf0e..8c98860640 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import org.bson.Document; import org.springframework.lang.Nullable; @@ -243,4 +244,21 @@ private String join(Iterable terms) { return StringUtils.collectionToDelimitedString(result, " "); } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof TextCriteria)) return false; + TextCriteria that = (TextCriteria) o; + return Objects.equals(terms, that.terms) && + Objects.equals(language, that.language) && + Objects.equals(caseSensitive, that.caseSensitive) && + Objects.equals(diacriticSensitive, that.diacriticSensitive); + } + + @Override + public int hashCode() { + return Objects.hash(terms, language, caseSensitive, diacriticSensitive); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java index ab2b4d9e4e..397097abf1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java @@ -103,6 +103,13 @@ public void diacriticSensitiveOperatorShouldBeSetCorrectly() { .isEqualTo(new Document("$search", "coffee").append("$diacriticSensitive", true)); } + @Test // DATAMONGO-2504 + public void twoIdenticalCriteriaShouldBeEqual() { + TextCriteria criteriaOne = TextCriteria.forDefaultLanguage().matching("coffee"); + TextCriteria criteriaTwo = TextCriteria.forDefaultLanguage().matching("coffee"); + assertThat(criteriaOne).isEqualTo(criteriaTwo); + } + private Document searchObject(String json) { return new Document("$text", Document.parse(json)); } From f4d2fc6231b24c9f6ab2af3116f9f9a1ee6febfa Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 23 Apr 2020 12:23:54 +0200 Subject: [PATCH 0151/1381] DATAMONGO-2504 - Polishing. Update equals/hashCode implementation to use the Spring Data form. Make fields final where possible. Use diamond syntax. Reorder methods. Reformat code. Extend tests. Original pull request: #848. --- .../data/mongodb/core/query/Term.java | 60 +++++++++++++----- .../data/mongodb/core/query/TextCriteria.java | 63 ++++++++++++------- .../core/query/TextCriteriaUnitTests.java | 40 ++++++++---- 3 files changed, 114 insertions(+), 49 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java index 379445a84c..f7504a417c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java @@ -15,8 +15,10 @@ */ package org.springframework.data.mongodb.core.query; -import java.util.Objects; +import static org.springframework.util.ObjectUtils.*; + import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; /** * A {@link Term} defines one or multiple words {@link Type#WORD} or phrases {@link Type#PHRASE} to be used in the @@ -91,6 +93,47 @@ public String getFormatted() { return negated ? negateRaw(formatted) : formatted; } + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (this == o) { + return true; + } + + if (!(o instanceof Term)) { + return false; + } + + Term term = (Term) o; + + return ObjectUtils.nullSafeEquals(negated, term.negated) && ObjectUtils.nullSafeEquals(type, term.type) + && ObjectUtils.nullSafeEquals(raw, term.raw); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + + int result = 17; + + result += ObjectUtils.nullSafeHashCode(type); + result += ObjectUtils.nullSafeHashCode(raw); + result += ObjectUtils.nullSafeHashCode(negated); + + return result; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return getFormatted(); @@ -103,19 +146,4 @@ protected String quotePhrase(String raw) { protected String negateRaw(String raw) { return "-" + raw; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Term)) return false; - Term term = (Term) o; - return negated == term.negated && - type == term.type && - Objects.equals(raw, term.raw); - } - - @Override - public int hashCode() { - return Objects.hash(type, raw, negated); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java index 8c98860640..424a40813b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java @@ -17,11 +17,11 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import org.bson.Document; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -35,7 +35,7 @@ public class TextCriteria implements CriteriaDefinition { private final List terms; - private @Nullable String language; + private final @Nullable String language; private @Nullable Boolean caseSensitive; private @Nullable Boolean diacriticSensitive; @@ -52,7 +52,7 @@ public TextCriteria() { private TextCriteria(@Nullable String language) { this.language = language; - this.terms = new ArrayList(); + this.terms = new ArrayList<>(); } /** @@ -232,9 +232,47 @@ public Document getCriteriaObject() { return new Document("$text", document); } + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (this == o) { + return true; + } + if (!(o instanceof TextCriteria)) { + return false; + } + + TextCriteria that = (TextCriteria) o; + + return ObjectUtils.nullSafeEquals(terms, that.terms) && ObjectUtils.nullSafeEquals(language, that.language) + && ObjectUtils.nullSafeEquals(caseSensitive, that.caseSensitive) + && ObjectUtils.nullSafeEquals(diacriticSensitive, that.diacriticSensitive); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + + int result = 17; + + result += ObjectUtils.nullSafeHashCode(terms); + result += ObjectUtils.nullSafeHashCode(language); + result += ObjectUtils.nullSafeHashCode(caseSensitive); + result += ObjectUtils.nullSafeHashCode(diacriticSensitive); + + return result; + } + private String join(Iterable terms) { - List result = new ArrayList(); + List result = new ArrayList<>(); for (Term term : terms) { if (term != null) { @@ -244,21 +282,4 @@ private String join(Iterable terms) { return StringUtils.collectionToDelimitedString(result, " "); } - - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof TextCriteria)) return false; - TextCriteria that = (TextCriteria) o; - return Objects.equals(terms, that.terms) && - Objects.equals(language, that.language) && - Objects.equals(caseSensitive, that.caseSensitive) && - Objects.equals(diacriticSensitive, that.diacriticSensitive); - } - - @Override - public int hashCode() { - return Objects.hash(terms, language, caseSensitive, diacriticSensitive); - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java index 397097abf1..0ef553218f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextCriteriaUnitTests.java @@ -26,88 +26,104 @@ * Unit tests for {@link TextCriteria}. * * @author Christoph Strobl + * @author Daniel Debray */ -public class TextCriteriaUnitTests { +class TextCriteriaUnitTests { @Test // DATAMONGO-850 - public void shouldNotHaveLanguageField() { + void shouldNotHaveLanguageField() { TextCriteria criteria = TextCriteria.forDefaultLanguage(); + assertThat(criteria.getCriteriaObject()).isEqualTo(searchObject("{ }")); } @Test // DATAMONGO-850 - public void shouldNotHaveLanguageForNonDefaultLanguageField() { + void shouldNotHaveLanguageForNonDefaultLanguageField() { TextCriteria criteria = TextCriteria.forLanguage("spanish"); + assertThat(criteria.getCriteriaObject()).isEqualTo(searchObject("{ \"$language\" : \"spanish\" }")); } @Test // DATAMONGO-850 - public void shouldCreateSearchFieldForSingleTermCorrectly() { + void shouldCreateSearchFieldForSingleTermCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().matching("cake"); + assertThat(criteria.getCriteriaObject()).isEqualTo(searchObject("{ \"$search\" : \"cake\" }")); } @Test // DATAMONGO-850 - public void shouldCreateSearchFieldCorrectlyForMultipleTermsCorrectly() { + void shouldCreateSearchFieldCorrectlyForMultipleTermsCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("bake", "coffee", "cake"); + assertThat(criteria.getCriteriaObject()).isEqualTo(searchObject("{ \"$search\" : \"bake coffee cake\" }")); } @Test // DATAMONGO-850 - public void shouldCreateSearchFieldForPhraseCorrectly() { + void shouldCreateSearchFieldForPhraseCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("coffee cake"); + assertThat(DocumentTestUtils.getAsDocument(criteria.getCriteriaObject(), "$text")) .isEqualTo(new Document("$search", "\"coffee cake\"")); } @Test // DATAMONGO-850 - public void shouldCreateNotFieldCorrectly() { + void shouldCreateNotFieldCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().notMatching("cake"); + assertThat(criteria.getCriteriaObject()).isEqualTo(searchObject("{ \"$search\" : \"-cake\" }")); } @Test // DATAMONGO-850 - public void shouldCreateSearchFieldCorrectlyForNotMultipleTermsCorrectly() { + void shouldCreateSearchFieldCorrectlyForNotMultipleTermsCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().notMatchingAny("bake", "coffee", "cake"); + assertThat(criteria.getCriteriaObject()).isEqualTo(searchObject("{ \"$search\" : \"-bake -coffee -cake\" }")); } @Test // DATAMONGO-850 - public void shouldCreateSearchFieldForNotPhraseCorrectly() { + void shouldCreateSearchFieldForNotPhraseCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().notMatchingPhrase("coffee cake"); + assertThat(DocumentTestUtils.getAsDocument(criteria.getCriteriaObject(), "$text")) .isEqualTo(new Document("$search", "-\"coffee cake\"")); } @Test // DATAMONGO-1455 - public void caseSensitiveOperatorShouldBeSetCorrectly() { + void caseSensitiveOperatorShouldBeSetCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().matching("coffee").caseSensitive(true); + assertThat(DocumentTestUtils.getAsDocument(criteria.getCriteriaObject(), "$text")) .isEqualTo(new Document("$search", "coffee").append("$caseSensitive", true)); } @Test // DATAMONGO-1456 - public void diacriticSensitiveOperatorShouldBeSetCorrectly() { + void diacriticSensitiveOperatorShouldBeSetCorrectly() { TextCriteria criteria = TextCriteria.forDefaultLanguage().matching("coffee").diacriticSensitive(true); + assertThat(DocumentTestUtils.getAsDocument(criteria.getCriteriaObject(), "$text")) .isEqualTo(new Document("$search", "coffee").append("$diacriticSensitive", true)); } @Test // DATAMONGO-2504 - public void twoIdenticalCriteriaShouldBeEqual() { + void twoIdenticalCriteriaShouldBeEqual() { + TextCriteria criteriaOne = TextCriteria.forDefaultLanguage().matching("coffee"); TextCriteria criteriaTwo = TextCriteria.forDefaultLanguage().matching("coffee"); + assertThat(criteriaOne).isEqualTo(criteriaTwo); + assertThat(criteriaOne).hasSameHashCodeAs(criteriaTwo); + assertThat(criteriaOne).isNotEqualTo(criteriaTwo.diacriticSensitive(false)); + assertThat(criteriaOne.hashCode()).isNotEqualTo(criteriaTwo.diacriticSensitive(false).hashCode()); } private Document searchObject(String json) { From 2af13c27a7e548d308e35f2e0d28c05cfbb6b62e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 23 Apr 2020 14:57:52 +0200 Subject: [PATCH 0152/1381] =?UTF-8?q?DATAMONGO-2529=20-=20Ensure=20that=20?= =?UTF-8?q?MappingMongoConverter.read(=E2=80=A6)=20is=20never=20called=20w?= =?UTF-8?q?ith=20null.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, various methods attempted to pass a null argument as source for the converter. The API is non-null and implementations relying on these constraints were easily breakable. We now make sure that the source is never null. --- .../data/mongodb/core/MongoTemplate.java | 14 +++++++------- .../core/convert/MappingMongoConverter.java | 11 +++++------ 2 files changed, 12 insertions(+), 13 deletions(-) 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 ea858d2dee..9d10d4fc0c 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 @@ -239,7 +239,8 @@ public MongoTemplate(MongoDatabaseFactory mongoDbFactory, @Nullable MongoConvert this.projectionFactory = new SpelAwareProxyProjectionFactory(); this.operations = new EntityOperations(this.mongoConverter.getMappingContext()); this.propertyOperations = new PropertyOperations(this.mongoConverter.getMappingContext()); - this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, propertyOperations, mongoDbFactory); + this.queryOperations = new QueryOperations(queryMapper, updateMapper, operations, propertyOperations, + mongoDbFactory); // We always have a mapping context in the converter, whether it's a simple one or not mappingContext = this.mongoConverter.getMappingContext(); @@ -1824,7 +1825,7 @@ public List mapReduce(Query query, Class domainType, String inputColle } Document mappedSort = getMappedSortObject(query, domainType); - if(mappedSort != null && !mappedSort.isEmpty()) { + if (mappedSort != null && !mappedSort.isEmpty()) { mapReduce = mapReduce.sort(getMappedSortObject(query, domainType)); } @@ -3122,12 +3123,13 @@ private class ReadDocumentCallback implements DocumentCallback { @Nullable public T doWith(@Nullable Document document) { + T source = null; + if (document != null) { maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); + source = reader.read(type, document); } - T source = reader.read(type, document); - if (source != null) { maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); source = maybeCallAfterConvert(source, document, collectionName); @@ -3168,9 +3170,7 @@ public T doWith(@Nullable Document document) { Class typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType : targetType; - if (document != null) { - maybeEmitEvent(new AfterLoadEvent<>(document, targetType, collectionName)); - } + maybeEmitEvent(new AfterLoadEvent<>(document, targetType, collectionName)); Object source = reader.read(typeToRead, document); Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; 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 592046bdd3..3ca5e2156c 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 @@ -252,11 +252,9 @@ protected S read(TypeInformation type, Bson bson) { @Nullable @SuppressWarnings("unchecked") - private S read(TypeInformation type, @Nullable Bson bson, ObjectPath path) { + private S read(TypeInformation type, Bson bson, ObjectPath path) { - if (null == bson) { - return null; - } + Assert.notNull(bson, "Bson must not be null!"); TypeInformation typeToUse = typeMapper.readType(bson, type); Class rawType = typeToUse.getType(); @@ -1640,13 +1638,14 @@ private List bulkReadAndConvertDBRefs(List dbrefs, TypeInformation for (Document document : referencedRawDocuments) { + T target = null; if (document != null) { + maybeEmitEvent( new AfterLoadEvent<>(document, (Class) (rawType != null ? rawType : Object.class), collectionName)); + target = (T) read(type, document, path); } - T target = (T) read(type, document, path); - if (target != null) { maybeEmitEvent(new AfterConvertEvent<>(document, target, collectionName)); target = maybeCallAfterConvert(target, document, collectionName); From 96ff4e1d147f813fc58eea26fde8845f60ec9576 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 24 Apr 2020 09:03:18 +0200 Subject: [PATCH 0153/1381] DATAMONGO-2461 - Polishing. Remove superfluous Test annotation as RepeatFailedTest acts as a TestTemplate so adding the Test annotation causes the test to run twice. --- .../core/ReactiveMongoTemplateIndexTests.java | 15 +++++---------- .../mongodb/core/messaging/ChangeStreamTests.java | 3 +-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java index 636dd05b19..a9865e2ec4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateIndexTests.java @@ -82,8 +82,7 @@ void setUp() { @AfterEach void cleanUp() {} - @Test // DATAMONGO-1444 - @RepeatFailedTest(3) + @RepeatFailedTest(3) // DATAMONGO-1444 void testEnsureIndexShouldCreateIndex() { Person p1 = new Person("Oliver"); @@ -119,8 +118,7 @@ void testEnsureIndexShouldCreateIndex() { }).verifyComplete(); } - @Test // DATAMONGO-1444 - @RepeatFailedTest(3) + @RepeatFailedTest(3) // DATAMONGO-1444 void getIndexInfoShouldReturnCorrectIndex() { Person p1 = new Person("Oliver"); @@ -150,8 +148,7 @@ void getIndexInfoShouldReturnCorrectIndex() { }).verifyComplete(); } - @Test // DATAMONGO-1444, DATAMONGO-2264 - @RepeatFailedTest(3) + @RepeatFailedTest(3) // DATAMONGO-1444, DATAMONGO-2264 void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { template.indexOps(Person.class).dropAllIndexes() // @@ -201,8 +198,7 @@ void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() { }).verifyComplete(); } - @Test // DATAMONGO-1928 - @RepeatFailedTest(3) + @RepeatFailedTest(3) // DATAMONGO-1928 void shouldCreateIndexOnAccess() { template.getCollection("indexedSample").flatMapMany(it -> it.listIndexes(Document.class)) // @@ -222,8 +218,7 @@ void shouldCreateIndexOnAccess() { .verifyComplete(); } - @Test // DATAMONGO-1928, DATAMONGO-2264 - @RepeatFailedTest(3) + @RepeatFailedTest(3) // DATAMONGO-1928, DATAMONGO-2264 void indexCreationShouldFail() throws InterruptedException { factory.getMongoDatabase() // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index 275f258959..435c89ca6d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -197,8 +197,7 @@ void useAggregationToFilterMessages() throws InterruptedException { assertThat(messageBodies).hasSize(2).doesNotContain(sugarSplashy); } - @Test // DATAMONGO-1803 - @RepeatFailedTest(3) + @RepeatFailedTest(3) // DATAMONGO-1803 void mapsTypedAggregationToFilterMessages() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); From 26ddf9d59fb8dda504d620fbdd6d035f92540c0c Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 27 Apr 2020 09:24:33 +0200 Subject: [PATCH 0154/1381] DATAMONGO-2531 - Fix MongoClientSettings UUID configuration hook in MongoConfigurationSupport. Client code overriding configureClientSettings does not automatically remove the default UUidRepresentation settings. --- .../data/mongodb/config/MongoConfigurationSupport.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index 9b094e537a..e946af8c55 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -217,6 +217,7 @@ protected boolean autoIndexCreation() { protected MongoClientSettings mongoClientSettings() { MongoClientSettings.Builder builder = MongoClientSettings.builder(); + builder.uuidRepresentation(UuidRepresentation.JAVA_LEGACY); configureClientSettings(builder); return builder.build(); } @@ -228,6 +229,6 @@ protected MongoClientSettings mongoClientSettings() { * @since 3.0 */ protected void configureClientSettings(MongoClientSettings.Builder builder) { - builder.uuidRepresentation(UuidRepresentation.JAVA_LEGACY); + // customization hook } } From 2f4f1e524d101d0a664e058dc15b859c693aeda2 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 11:32:19 +0200 Subject: [PATCH 0155/1381] DATAMONGO-2484 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 91ba4637ad..5131f49528 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.17.RELEASE (2020-04-28) +---------------------------------------------- +* DATAMONGO-2529 - EntityReader called with null argument. +* DATAMONGO-2497 - Update documentation regarding @Transient properties usage in the persistence constructor. +* DATAMONGO-2484 - Release 2.1.17 (Lovelace SR17). +* DATAMONGO-2300 - Can't read and convert DBRef when the type is Map. + + Changes in version 3.0.0.RC1 (2020-03-31) ----------------------------------------- * DATAMONGO-2501 - Upgrade to Querydsl 4.3. @@ -2978,3 +2986,4 @@ Repository + From 7dc509953a327120a868c37d7d67b6103aa1b7ef Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 14:35:16 +0200 Subject: [PATCH 0156/1381] DATAMONGO-2500 - Updated changelog. --- src/main/resources/changelog.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 5131f49528..bef42b36f3 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,18 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.7.RELEASE (2020-04-28) +--------------------------------------------- +* DATAMONGO-2529 - EntityReader called with null argument. +* DATAMONGO-2523 - ParameterBindingJsonReader skips too many chars. +* DATAMONGO-2517 - Text search fails on entity with second constructor. +* DATAMONGO-2513 - ComparisonOperators.Eq#equalToValue doesn't work well with Lists. +* DATAMONGO-2506 - StringBasedAggregation should raise meaningful error when unsupported return type requested. +* DATAMONGO-2504 - TextCriteria Hashcode and equals. +* DATAMONGO-2502 - Regression in Update property mapping. +* DATAMONGO-2500 - Release 2.2.7 (Moore SR7). + + Changes in version 2.1.17.RELEASE (2020-04-28) ---------------------------------------------- * DATAMONGO-2529 - EntityReader called with null argument. @@ -2987,3 +2999,4 @@ Repository + From 9751c6bc8bca30d7c98c43c5c654f96b7541fdf9 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 15:03:26 +0200 Subject: [PATCH 0157/1381] DATAMONGO-2503 - Updated changelog. --- src/main/resources/changelog.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index bef42b36f3..21d3ca9d00 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,24 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.RC2 (2020-04-28) +----------------------------------------- +* DATAMONGO-2531 - Fix MongoClientSettings UUID configuration hook in MongoConfigurationSupport. +* DATAMONGO-2529 - EntityReader called with null argument. +* DATAMONGO-2523 - ParameterBindingJsonReader skips too many chars. +* DATAMONGO-2517 - Text search fails on entity with second constructor. +* DATAMONGO-2516 - Assert compatibility with MongoDB 4.4-rc0. +* DATAMONGO-2513 - ComparisonOperators.Eq#equalToValue doesn't work well with Lists. +* DATAMONGO-2510 - Use JDK 14 for Java.NEXT CI testing. +* DATAMONGO-2508 - Upgrade to MongoDB 4.0.2 Drivers. +* DATAMONGO-2507 - Add default method accepting CriteriaDefinition on ReactiveFindOperation.DistinctWithQuery. +* DATAMONGO-2506 - StringBasedAggregation should raise meaningful error when unsupported return type requested. +* DATAMONGO-2505 - Deferred Database retrieval from ReactiveMongoDatabaseFactory. +* DATAMONGO-2504 - TextCriteria Hashcode and equals. +* DATAMONGO-2503 - Release 3.0 RC2 (Neumann). +* DATAMONGO-2502 - Regression in Update property mapping. + + Changes in version 2.2.7.RELEASE (2020-04-28) --------------------------------------------- * DATAMONGO-2529 - EntityReader called with null argument. @@ -3000,3 +3018,4 @@ Repository + From 5df22233d8b7c77ee5135bf488b6a1507606653b Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 15:03:33 +0200 Subject: [PATCH 0158/1381] DATAMONGO-2503 - Prepare 3.0 RC2 (Neumann). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index e5e41bf08c..62acbc2584 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.RC2 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.RC2 4.0.2 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 9462100533..c895699a72 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 RC1 +Spring Data MongoDB 3.0 RC2 Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -13,3 +13,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 0f987f44efa3c344732f80c212ec365b31dde6ba Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 15:03:53 +0200 Subject: [PATCH 0159/1381] DATAMONGO-2503 - Release version 3.0 RC2 (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 62acbc2584..129d19bd1f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC2 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..b3d553af12 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC2 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..3f3f94cb8c 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC2 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 872db5d428..7383dcd645 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RC2 ../pom.xml From d5cf3dfc22091b32c0386c12772567b5ba33a9d1 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 15:11:42 +0200 Subject: [PATCH 0160/1381] DATAMONGO-2503 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 129d19bd1f..62acbc2584 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC2 + 3.0.0.BUILD-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b3d553af12..b5dba6f53e 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC2 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 3f3f94cb8c..dbb3854812 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC2 + 3.0.0.BUILD-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 7383dcd645..872db5d428 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RC2 + 3.0.0.BUILD-SNAPSHOT ../pom.xml From 09fbe6060ef6fce1cb7655b3d7c4ecc72e246e25 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Apr 2020 15:11:43 +0200 Subject: [PATCH 0161/1381] DATAMONGO-2503 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 62acbc2584..e5e41bf08c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.RC2 + 2.3.0.BUILD-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.RC2 + 2.3.0.BUILD-SNAPSHOT 4.0.2 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 689c1480bd3d7a1845852ac660efcf0474624e99 Mon Sep 17 00:00:00 2001 From: Greg Turnquist Date: Mon, 4 May 2020 15:09:00 -0500 Subject: [PATCH 0162/1381] DATAMONGO-2535 - Remove Travis CI. --- .travis.yml | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 30fcd9ca29..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -language: java - -before_install: - - mkdir -p downloads - - mkdir -p var/db var/log - - if [[ ! -d downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION} ]] ; then cd downloads && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}.tgz && tar xzf mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}.tgz && cd ..; fi - - downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongod --version - - downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongod --dbpath var/db --replSet rs0 --fork --logpath var/log/mongod.log - - sleep 10 - - |- - downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongo --eval "rs.initiate({_id: 'rs0', members:[{_id: 0, host: '127.0.0.1:27017'}]});" - sleep 15 - -jdk: - - openjdk13 - - openjdk-ea - -matrix: - allow_failures: - - jdk: openjdk-ea - -env: - matrix: - - MONGO_VERSION=4.2.0 - - MONGO_VERSION=4.0.14 - - MONGO_VERSION=3.6.16 - global: - - PROFILE=ci - -sudo: false - -cache: - directories: - - $HOME/.m2 - - downloads - -install: true - -script: - - "./mvnw clean dependency:list test -Pjava11 -Dsort -U" From 288e04b2d3e98a54452defb6ffcaaa8277f9ce0e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 9 Apr 2020 13:16:37 +0200 Subject: [PATCH 0163/1381] DATAMONGO-2509 - Update Reference Documentation. Related to: DATAMONGO-365, DATAMONGO-384, DATAMONGO-2192, DATAMONGO-2407 Original pull request: #853. --- README.adoc | 5 - src/main/asciidoc/index.adoc | 1 - src/main/asciidoc/reference/cross-store.adoc | 260 ------------------ src/main/asciidoc/reference/mapping.adoc | 17 +- .../reference/mongo-custom-conversions.adoc | 6 - .../reference/mongo-repositories.adoc | 5 - src/main/asciidoc/reference/mongodb.adoc | 170 ++++++++---- 7 files changed, 124 insertions(+), 340 deletions(-) delete mode 100644 src/main/asciidoc/reference/cross-store.adoc diff --git a/README.adoc b/README.adoc index cbd524c70e..a6b69f9747 100644 --- a/README.adoc +++ b/README.adoc @@ -52,11 +52,6 @@ public class MyService { @EnableMongoRepositories class ApplicationConfig extends AbstractMongoClientConfiguration { - @Override - public MongoClient mongoClient() { - return MongoClients.create(); - } - @Override protected String getDatabaseName() { return "springdata"; diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 12a4390423..9464e7da80 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -32,7 +32,6 @@ include::reference/mongo-auditing.adoc[leveloffset=+1] include::reference/mapping.adoc[leveloffset=+1] include::reference/sharding.adoc[leveloffset=+1] include::reference/kotlin.adoc[leveloffset=+1] -include::reference/cross-store.adoc[leveloffset=+1] include::reference/jmx.adoc[leveloffset=+1] include::reference/mongo-3.adoc[leveloffset=+1] diff --git a/src/main/asciidoc/reference/cross-store.adoc b/src/main/asciidoc/reference/cross-store.adoc deleted file mode 100644 index 8dafade0b3..0000000000 --- a/src/main/asciidoc/reference/cross-store.adoc +++ /dev/null @@ -1,260 +0,0 @@ -[[mongo.cross.store]] -= Cross Store Support - -WARNING: This feature has been deprecated and will be removed without replacement. - -Sometimes you need to store data in multiple data stores, and these data stores need to be of different types. One might be relational while the other is a document store. For this use case, we created a separate module in the MongoDB support that handles what we call "`cross-store support`". The current implementation is based on JPA as the driver for the relational database and we let select fields in the Entities be stored in a Mongo database. In addition to letting you store your data in two stores, we also coordinate persistence operations for the non-transactional MongoDB store with the transaction life-cycle for the relational database. - -[[mongodb_cross-store-configuration]] -== Cross Store Configuration - -Assuming that you have a working JPA application and would like to add some cross-store persistence for MongoDB, what do you have to add to your configuration? - -First, you need to add a dependency on the cross-store module. If you use Maven, you can add the following dependency to your pom: - -.Example Maven pom.xml with `spring-data-mongodb-cross-store` dependency -==== -[source,xml] ----- - - 4.0.0 - - ... - - - - org.springframework.data - spring-data-mongodb-cross-store - ${spring.data.mongo.version} - - - ... - - ----- -==== - -Once you have added the dependency, you need to enable AspectJ for the project. The cross-store support is implemented with AspectJ aspects so, if you enable compile-time AspectJ support, the cross-store features become available to your project. In Maven, you would add an additional plugin to the `` section of the pom, as follows: - -.Example Maven pom.xml with AspectJ plugin enabled -==== -[source,xml] ----- - - 4.0.0 - - ... - - - - - … - - - org.codehaus.mojo - aspectj-maven-plugin - 1.0 - - - - org.aspectj - aspectjrt - ${aspectj.version} - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - compile - test-compile - - - - - true - - - org.springframework - spring-aspects - - - org.springframework.data - spring-data-mongodb-cross-store - - - 1.6 - 1.6 - - - - ... - - - - -... - - ----- -==== - -Finally, you need to configure your project to use MongoDB and also configure which aspects are used. You should add the following XML snippet to your application context: - -.Example application context with MongoDB and cross-store aspect support -==== -[source,xml] ----- - - - - ... - - - - - - - - - - - - - - - - - - - - - - ... - - ----- -==== - -[[mongodb_cross-store-application]] -== Writing the Cross Store Application - -We assume that you have a working JPA application, so we cover only the additional steps needed to persist part of your entity in your Mongo database. To do so, you need to identify the field you want to persist. It should be a domain class and follow the general rules for the Mongo mapping support covered in previous chapters. The field you want to persist in MongoDB should be annotated with the `@RelatedDocument` annotation. That is really all you need to do. The cross-store aspects take care of the rest, including: - -* Marking the field with `@Transient` so that it will not be persisted by JPA -* Keeping track of any changes made to the field value and writing them to the database on successful transaction completion -* Loading the document from MongoDB the first time the value is used in your application. - -The following example shows an entity that has a field annotated with `@RelatedDocument`: - -.Example of Entity with @RelatedDocument -==== -[source,java] ----- -@Entity -public class Customer { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String firstName; - - private String lastName; - - @RelatedDocument - private SurveyInfo surveyInfo; - - // getters and setters omitted -} ----- -==== - -The following example shows a domain class that is to be stored as a `Document`: - -.Example of a domain class to be stored as a Document -==== -[source,java] ----- -public class SurveyInfo { - - private Map questionsAndAnswers; - - public SurveyInfo() { - this.questionsAndAnswers = new HashMap(); - } - - public SurveyInfo(Map questionsAndAnswers) { - this.questionsAndAnswers = questionsAndAnswers; - } - - public Map getQuestionsAndAnswers() { - return questionsAndAnswers; - } - - public void setQuestionsAndAnswers(Map questionsAndAnswers) { - this.questionsAndAnswers = questionsAndAnswers; - } - - public SurveyInfo addQuestionAndAnswer(String question, String answer) { - this.questionsAndAnswers.put(question, answer); - return this; - } -} ----- -==== - -In the preceding example, once the `SurveyInfo` has been set on the `Customer` object, the `MongoTemplate` that was configured previously is used to save the `SurveyInfo` (along with some metadata about the JPA Entity) in a MongoDB collection named after the fully qualified name of the JPA Entity class. The following code shows how to configure a JPA entity for cross-store persistence with MongoDB: - -.Example of code using the JPA Entity configured for cross-store persistence -==== -[source,java] ----- -Customer customer = new Customer(); -customer.setFirstName("Sven"); -customer.setLastName("Olafsen"); -SurveyInfo surveyInfo = new SurveyInfo() - .addQuestionAndAnswer("age", "22") - .addQuestionAndAnswer("married", "Yes") - .addQuestionAndAnswer("citizenship", "Norwegian"); -customer.setSurveyInfo(surveyInfo); -customerRepository.save(customer); ----- -==== - -Running the preceding above results in the following JSON document being stored in MongoDB: - -.Example of JSON document stored in MongoDB -==== -[source,javascript] ----- -{ "_id" : ObjectId( "4d9e8b6e3c55287f87d4b79e" ), - "_entity_id" : 1, - "_entity_class" : "org.springframework.data.mongodb.examples.custsvc.domain.Customer", - "_entity_field_name" : "surveyInfo", - "questionsAndAnswers" : { "married" : "Yes", - "age" : "22", - "citizenship" : "Norwegian" }, - "_entity_field_class" : "org.springframework.data.mongodb.examples.custsvc.domain.SurveyInfo" } ----- -==== diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 8e2736f2cf..55cc5623d7 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -269,15 +269,8 @@ You can configure the `MappingMongoConverter` as well as `com.mongodb.client.Mon ==== [source,java] ---- -import com.mongodb.client.MongoClients; - @Configuration -public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { - - @Bean - public MongoClient mongoClient() { - return MongoClients.create("monogodb://localhost:27017"); - } +public class MongoConfig extends AbstractMongoClientConfiguration { @Override public String getDatabaseName() { @@ -287,12 +280,12 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { // the following are optional @Override - public String getMappingBasePackage() { + public String getMappingBasePackage() { <1> return "com.bigbank.domain"; } @Override - void configureConverters(MongoConverterConfigurationAdapter adapter) { + void configureConverters(MongoConverterConfigurationAdapter adapter) { <2> adapter.registerConverter(new org.springframework.data.mongodb.test.PersonReadConverter()); adapter.registerConverter(new org.springframework.data.mongodb.test.PersonWriteConverter()); @@ -304,6 +297,8 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { } } ---- +<1> The mapping base package defines the root path used to scan for entities used to pre initialize the `MappingContext`. By default the configuration classes package is used. +<2> Configure additional custom converters for specific domain types that replace the default mapping procedure for those types with your custom implementation. ==== `AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. @@ -390,6 +385,8 @@ public class Person { IMPORTANT: The `@Id` annotation tells the mapper which property you want to use for the MongoDB `_id` property, and the `@Indexed` annotation tells the mapping framework to call `createIndex(…)` on that property of your document, making searches faster. Automatic index creation is only done for types annotated with `@Document`. +WARNING: Auto index creation is turned **OFF** by default and need to be enabled via the configuration (see <>). + [[mapping.index-creation]] === Index Creation diff --git a/src/main/asciidoc/reference/mongo-custom-conversions.adoc b/src/main/asciidoc/reference/mongo-custom-conversions.adoc index 0032487551..5150b24829 100644 --- a/src/main/asciidoc/reference/mongo-custom-conversions.adoc +++ b/src/main/asciidoc/reference/mongo-custom-conversions.adoc @@ -94,12 +94,6 @@ class MyMongoConfiguration extends AbstractMongoClientConfiguration { return "database"; } - @Override - @Bean - public MongoClient mongoClient() { - return MongoClients.create(); - } - @Override protected void configureConverters(MongoConverterConfigurationAdapter adapter) { adapter.registerConverter(new com.example.PersonReadConverter()); diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index f1fc60af1a..e10af2975b 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -64,11 +64,6 @@ class ApplicationConfig extends AbstractMongoClientConfiguration { return "e-store"; } - @Override - public MongoClient mongoClient() { - return MongoClients.create(); - } - @Override protected String getMappingBasePackage() { return "com.oreilly.springdata.mongodb"; diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index a29aefe768..7ee3ac6240 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -349,17 +349,13 @@ public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientCo } @Override - @Bean - public MongoClient mongoClient() { + protected void configureClientSettings(Builder builder) { - MongoClientSettings settings = MongoClientSettings.builder() + builder .credential(MongoCredential.createCredential("name", "db", "pwd".toCharArray())) .applyToClusterSettings(settings -> { settings.hosts(singletonList(new ServerAddress("127.0.0.1", 27017))); - }) - .build(); - - return MongoClients.create(settings); + }); } } ---- @@ -371,23 +367,6 @@ The following example shows encoded credentials: `m0ng0@dmin:mo_res:bw6},Qsdxx@admin@database` -> `m0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database` See https://tools.ietf.org/html/rfc3986#section-2.2[section 2.2 of RFC 3986] for further details. -[source,java] ----- -@Configuration -public class MongoClientConfiguration extends AbstractMongoClientConfiguration { - - @Override - protected String getDatabaseName() { - return "database"; - } - - @Override - public MongoClient mongoClient() { - return MongoClients.create("mongodb://localhost:27017/?replicaSet=rs0&w=majority"); - } -} ----- - [[mongo.mongo-db-factory-xml]] === Registering a `MongoDatabaseFactory` Instance by Using XML-based Metadata @@ -737,6 +716,25 @@ class Person { Note that the resulting document contains `pers` as the value in the `_class` Field. +[WARNING] +==== +Type aliases only work if the mapping context is aware of the actual type. The required entity metadata is aquired either on first save or has to be provided via the configurations initial entity set. By default the configuration base package is scanned for potential candidates. + +[source,java] +---- +@Configuration +public class AppConfig extends AbstractMongoClientConfiguration { + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(Person.class); + } + + // ... +} +---- +==== + ==== Configuring Custom Type Mapping The following example shows how to configure a custom `MongoTypeMapper` in `MappingMongoConverter`: @@ -761,11 +759,6 @@ class SampleMongoConfiguration extends AbstractMongoClientConfiguration { return "database"; } - @Override - public MongoClient mongoClient() { - return MongoClients.create(); - } - @Bean @Override public MappingMongoConverter mappingMongoConverter() throws Exception { @@ -935,7 +928,10 @@ Related to performing an `updateFirst` operation, you can also perform an "`upse [source] ---- -template.upsert(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")), update("address", addr), Person.class); +template.update(Person.class) + .matching(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")) + .apply(update("address", addr)) + .upsert(); ---- WARNING: `upsert` does not support ordering. Please use <> to apply `Sort`. @@ -960,32 +956,48 @@ The following example inserts a few `Person` objects into the container and perf [source,java] ---- -mongoTemplate.insert(new Person("Tom", 21)); -mongoTemplate.insert(new Person("Dick", 22)); -mongoTemplate.insert(new Person("Harry", 23)); +template.insert(new Person("Tom", 21)); +template.insert(new Person("Dick", 22)); +template.insert(new Person("Harry", 23)); Query query = new Query(Criteria.where("firstName").is("Harry")); Update update = new Update().inc("age", 1); -Person p = mongoTemplate.findAndModify(query, update, Person.class); // return's old person object -assertThat(p.getFirstName(), is("Harry")); -assertThat(p.getAge(), is(23)); -p = mongoTemplate.findOne(query, Person.class); -assertThat(p.getAge(), is(24)); +Person oldValue = template.update(Person.class) + .matching(query) + .apply(update) + .findAndModifyValue(); // return's old person object + +assertThat(oldValue.getFirstName(), is("Harry")); +assertThat(oldValue.getAge(), is(23)); + +Person newValue = template.query(Person.class) + .matching(query) + .findOneValue(); + +assertThat(newValue.getAge(), is(24)); -// Now return the newly updated document when updating -p = template.findAndModify(query, update, new FindAndModifyOptions().returnNew(true), Person.class); -assertThat(p.getAge(), is(25)); +Person newestValue = template.update(Person.class) + .matching(query) + .apply(update) + .withOptions(FindAndModifyOptions.options().returnNew(true)) // Now return the newly updated document when updating + .findAndModifyValue(); + +assertThat(newestValue.getAge(), is(25)); ---- The `FindAndModifyOptions` method lets you set the options of `returnNew`, `upsert`, and `remove`. An example extending from the previous code snippet follows: [source,java] ---- -Query query2 = new Query(Criteria.where("firstName").is("Mary")); -p = mongoTemplate.findAndModify(query2, update, new FindAndModifyOptions().returnNew(true).upsert(true), Person.class); -assertThat(p.getFirstName(), is("Mary")); -assertThat(p.getAge(), is(1)); +Person upserted = template.update(Person.class) + .matching(new Query(Criteria.where("firstName").is("Mary"))) + .apply(update) + .withOptions(FindAndModifyOptions.options().upsert(true).returnNew(true)) + .findAndModifyValue() + +assertThat(upserted.getFirstName(), is("Mary")); +assertThat(upserted.getAge(), is(1)); ---- [[mongo-template.aggregation-update]] @@ -1166,10 +1178,11 @@ Earlier, we saw how to retrieve a single document by using the `findOne` and `fi import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; -… +// ... -List result = mongoTemplate.find(query(where("age").lt(50) - .and("accounts.balance").gt(1000.00d)), Person.class); +List result = template.query(Person.class) + .matching(query(where("age").lt(50).and("accounts.balance").gt(1000.00d))) + .all(); ---- ==== @@ -1709,13 +1722,35 @@ db.foo.createIndex( ) ---- -A query searching for `coffee cake`, sorted by relevance according to the `weights`, can be defined and executed as follows: +A query searching for `coffee cake` can be defined and executed as follows: +.Full Text Query +==== [source,java] ---- -Query query = TextQuery.searching(new TextCriteria().matchingAny("coffee", "cake")).sortByScore(); +Query query = TextQuery + .searching(new TextCriteria().matchingAny("coffee", "cake")); + List page = template.find(query, Document.class); ---- +==== + +To sort results by relevance according to the `weights` use `TextQuery.sortByScore`. + +.Full Text Query - Sort by Score +==== +[source,java] +---- +Query query = TextQuery + .searching(new TextCriteria().matchingAny("coffee", "cake")) + .sortByScore() <1> + .includeScore(); <2> + +List page = template.find(query, Document.class); +---- +<1> Use the score property for sorting results by relevance which triggers `.sort({'score': {'$meta': 'textScore'}})`. +<2> Use `TextQuery.includeScore()` to include the calculated relevance in the resulting `Document`. +==== You can exclude search terms by prefixing the term with `-` or by using `notMatching`, as shown in the following example (note that the two lines have the same effect and are thus redundant): @@ -1941,6 +1976,8 @@ JsonSchemaProperty.named("birthdate").ofType(Type.dateType()); JsonSchemaProperty.named("birthdate").with(JsonSchemaObject.of(Type.dateType()).description("Must be a date")); ---- +The Schema builder also provides support for https://docs.mongodb.com/manual/core/security-client-side-encryption/[Client-Side Field Level Encryption]. Please refer to <> for more information, + `CollectionOptions` provides the entry point to schema support for collections, as the following example shows: .Create collection with `$jsonSchema` @@ -2155,11 +2192,9 @@ directly there are several methods for those options. Query query = query(where("firstname").is("luke")) .comment("find luke") <1> .batchSize(100) <2> - .slaveOk(); <3> ---- <1> The comment propagated to the MongoDB profile log. <2> The number of documents to return in each response batch. -<3> Allows querying a replica slave. ==== On the repository level the `@Meta` annotation provides means to add query options in a declarative way. @@ -2175,6 +2210,35 @@ List findByFirstname(String firstname); include::../{spring-data-commons-docs}/query-by-example.adoc[leveloffset=+1] include::query-by-example.adoc[leveloffset=+1] +[[mongo.query.count]] +== Counting Documents + +In pre 3.x versions of SpringData MongoDB the count operation was executed against MongoDBs internal collection statistics. +With the introduction of <> this was no longer possible because statistics would not correctly reflect potential changes during a transaction requiring an aggregation based count approach. +So in 2.x `MongoOperations.count()` would use the collection statistics if no transaction was in progress, and the aggregation variant if so. + +As off Spring Data MongoDB 3.x any `count` operation, may it be with our without a filter query, uses the aggregation based count approach via MongoDBs `countDocuments`. + +[NOTE] +==== +MongoDBs native `countDocuments` method, and the executed `$match` aggregation, does not support `$near` and `$nearSphere` but require `$geoWithin` along with `$center` or `$centerSphere` which does not support `$minDistance` (see https://jira.mongodb.org/browse/SERVER-37043). + +Therefore a given `Query` will be rewritten for `count` operations using `Reactive`-/`MongoTemplate` to bypass the issue like shown below. + +[source,javascript] +---- +{ location : { $near : [-73.99171, 40.738868], $maxDistance : 1.1 } } <1> +{ location : { $geoWithin : { $center: [ [-73.99171, 40.738868], 1.1] } } } <2> + +{ location : { $near : [-73.99171, 40.738868], $minDistance : 0.1, $maxDistance : 1.1 } } <3> +{$and :[ { $nor :[ { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868 ], 0.01] } } } ]}, { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868 ], 1.1] } } } ] } <4> +---- +<1> Count source query using `$near`. +<2> Rewritten query now using `$geoWithin` with `$center`. +<3> Count source query using `$near` with `$minDistance` and `$maxDistance`. +<4> Rewritten query now a combination of `$nor` `$geowithin` critierias to work aournd unsupported `$minDistance`. +==== + [[mongo.mapreduce]] == Map-Reduce Operations @@ -2309,7 +2373,7 @@ Note that you can specify additional limit and sort values on the query, but you ==== https://docs.mongodb.com/master/release-notes/4.2-compatibility/[MongoDB 4.2] removed support for the `eval` command used by `ScriptOperations`. + -There is no replacement for the removed functionallity. +There is no replacement for the removed functionality. ==== MongoDB allows executing JavaScript functions on the server by either directly sending the script or calling a stored one. `ScriptOperations` can be accessed through `MongoTemplate` and provides basic abstraction for `JavaScript` usage. The following example shows how to us the `ScriptOperations` class: From 37d99c4948090820904820861982c493d2d8ecbd Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 10 Apr 2020 12:04:34 +0200 Subject: [PATCH 0164/1381] DATAMONGO-2509 - Update Javadoc. Original pull request: #853. --- .../data/mongodb/LazyLoadingException.java | 6 +- .../data/mongodb/MongoDatabaseFactory.java | 2 +- .../data/mongodb/MongoDbFactory.java | 4 +- .../mongodb/ReactiveMongoDatabaseFactory.java | 4 +- .../mongodb/config/EnableMongoAuditing.java | 8 +- .../config/MongoConfigurationSupport.java | 2 +- .../data/mongodb/core/BulkOperations.java | 3 - .../data/mongodb/core/CollectionCallback.java | 2 +- .../data/mongodb/core/CollectionOptions.java | 2 +- .../data/mongodb/core/CursorPreparer.java | 7 +- .../mongodb/core/DocumentCallbackHandler.java | 2 +- .../data/mongodb/core/EntityOperations.java | 10 +- .../core/ExecutableAggregationOperation.java | 4 +- .../mongodb/core/ExecutableFindOperation.java | 2 +- .../core/ExecutableFindOperationSupport.java | 4 +- .../mongodb/core/FindAndModifyOptions.java | 8 +- .../mongodb/core/FindAndReplaceOptions.java | 4 +- .../mongodb/core/FindPublisherPreparer.java | 2 +- .../mongodb/core/GeoCommandStatistics.java | 4 +- .../data/mongodb/core/MongoOperations.java | 6 +- .../data/mongodb/core/MongoTemplate.java | 4 +- .../mongodb/core/ReactiveMongoOperations.java | 6 +- .../mongodb/core/ReactiveMongoTemplate.java | 7 +- .../mongodb/core/WriteResultChecking.java | 4 +- .../aggregation/AccumulatorOperators.java | 64 ++-- .../mongodb/core/aggregation/Aggregation.java | 61 ++-- .../aggregation/AggregationExpression.java | 4 +- .../AggregationExpressionTransformer.java | 6 +- .../AggregationFunctionExpressions.java | 2 +- .../AggregationOperationContext.java | 12 +- .../core/aggregation/AggregationOptions.java | 42 +-- .../core/aggregation/AggregationResults.java | 8 +- .../AggregationSpELExpression.java | 2 +- .../core/aggregation/AggregationUpdate.java | 6 +- .../core/aggregation/AggregationUtils.java | 4 +- .../core/aggregation/ArithmeticOperators.java | 288 +++++++++++++----- .../core/aggregation/ArrayOperators.java | 186 ++++++----- .../core/aggregation/BooleanOperators.java | 40 +-- .../core/aggregation/BucketAutoOperation.java | 6 +- .../core/aggregation/BucketOperation.java | 6 +- .../aggregation/BucketOperationSupport.java | 51 ++-- .../core/aggregation/ComparisonOperators.java | 118 +++---- .../aggregation/ConditionalOperators.java | 77 ++--- .../core/aggregation/CountOperation.java | 6 +- .../core/aggregation/DataTypeOperators.java | 4 +- .../core/aggregation/DateOperators.java | 91 +++--- .../core/aggregation/ExposedFields.java | 18 +- .../aggregation/GraphLookupOperation.java | 16 +- .../core/aggregation/LookupOperation.java | 10 +- .../core/aggregation/MergeOperation.java | 6 +- .../aggregation/ReplaceRootOperation.java | 10 +- .../aggregation/ReplaceWithOperation.java | 2 +- .../core/aggregation/SetOperators.java | 78 ++--- .../core/aggregation/StringOperators.java | 143 +++++---- .../core/convert/AbstractMongoConverter.java | 2 +- .../core/convert/CustomConversions.java | 2 +- .../mongodb/core/convert/DbRefResolver.java | 6 +- .../core/convert/DefaultMongoTypeMapper.java | 7 +- .../core/convert/DocumentAccessor.java | 10 +- .../mongodb/core/convert/GeoConverters.java | 10 +- .../core/convert/MappingMongoConverter.java | 2 +- .../mongodb/core/convert/MongoConverter.java | 4 +- .../mongodb/core/convert/QueryMapper.java | 4 +- .../mongodb/core/convert/ValueResolver.java | 2 +- .../data/mongodb/core/geo/GeoJson.java | 2 +- .../core/geo/GeoJsonGeometryCollection.java | 2 +- .../data/mongodb/core/geo/Sphere.java | 10 +- .../mongodb/core/index/CompoundIndex.java | 16 +- .../mongodb/core/index/GeoSpatialIndexed.java | 16 +- .../mongodb/core/index/GeospatialIndex.java | 30 +- .../data/mongodb/core/index/HashedIndex.java | 2 +- .../data/mongodb/core/index/Index.java | 20 +- .../mongodb/core/index/IndexDefinition.java | 10 + .../data/mongodb/core/index/IndexField.java | 2 +- .../data/mongodb/core/index/IndexFilter.java | 2 +- .../data/mongodb/core/index/IndexInfo.java | 6 +- .../mongodb/core/index/IndexResolver.java | 4 +- .../data/mongodb/core/index/Indexed.java | 19 +- .../MongoPersistentEntityIndexCreator.java | 2 +- .../mapping/BasicMongoPersistentEntity.java | 4 +- .../mapping/BasicMongoPersistentProperty.java | 8 +- .../CachingMongoPersistentProperty.java | 10 +- .../data/mongodb/core/mapping/DBRef.java | 4 +- .../data/mongodb/core/mapping/Document.java | 2 +- .../core/mapping/MongoPersistentEntity.java | 2 +- .../mapping/event/AbstractDeleteEvent.java | 2 +- .../core/mapping/event/AfterDeleteEvent.java | 2 +- .../core/mapping/event/AfterLoadEvent.java | 2 +- .../mongodb/core/messaging/Cancelable.java | 2 +- .../core/messaging/CursorReadingTask.java | 2 +- .../data/mongodb/core/messaging/Message.java | 4 +- .../messaging/MessageListenerContainer.java | 4 +- .../data/mongodb/core/query/Collation.java | 30 +- .../data/mongodb/core/query/Criteria.java | 214 ++++++------- .../data/mongodb/core/query/GeoCommand.java | 3 +- .../data/mongodb/core/query/Query.java | 38 +-- .../data/mongodb/core/query/TextQuery.java | 22 +- .../data/mongodb/core/query/Update.java | 114 +++---- .../IdentifiableJsonSchemaProperty.java | 9 +- .../core/schema/JsonSchemaProperty.java | 8 +- .../mongodb/core/schema/MongoJsonSchema.java | 26 +- .../core/schema/TypedJsonSchemaObject.java | 3 +- .../core/schema/UntypedJsonSchemaObject.java | 2 +- .../data/mongodb/gridfs/GridFsCriteria.java | 12 +- .../data/mongodb/gridfs/GridFsOperations.java | 4 +- .../data/mongodb/gridfs/GridFsTemplate.java | 2 +- .../data/mongodb/gridfs/GridFsUpload.java | 2 +- .../data/mongodb/monitor/AbstractMonitor.java | 2 +- .../data/mongodb/monitor/AssertMetrics.java | 2 +- .../monitor/BackgroundFlushingMetrics.java | 2 +- .../mongodb/monitor/BtreeIndexCounters.java | 2 +- .../mongodb/monitor/ConnectionMetrics.java | 2 +- .../mongodb/monitor/GlobalLockMetrics.java | 2 +- .../data/mongodb/repository/CountQuery.java | 2 +- .../data/mongodb/repository/DeleteQuery.java | 2 +- .../data/mongodb/repository/ExistsQuery.java | 2 +- .../data/mongodb/repository/Meta.java | 4 +- .../mongodb/repository/MongoRepository.java | 2 +- .../data/mongodb/repository/Query.java | 12 +- .../config/EnableMongoRepositories.java | 19 +- .../EnableReactiveMongoRepositories.java | 16 +- .../query/ConvertingParameterAccessor.java | 6 +- .../query/DtoInstantiatingConverter.java | 8 +- .../data/mongodb/util/json/package-info.java | 21 ++ .../data/mongodb/core/MongoTemplateTests.java | 6 +- 125 files changed, 1291 insertions(+), 1024 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java index 67ca617d13..0ec364f6c8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java @@ -25,8 +25,10 @@ public class LazyLoadingException extends UncategorizedDataAccessException { private static final long serialVersionUID = -7089224903873220037L; /** - * @param msg - * @param cause + * Constructor for LazyLoadingException. + * + * @param msg the detail message. + * @param cause the exception thrown by underlying data access API. */ public LazyLoadingException(String msg, Throwable cause) { super(msg, cause); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java index 846a527271..96620d8f8a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java @@ -45,7 +45,7 @@ public interface MongoDatabaseFactory extends CodecRegistryProvider, MongoSessio /** * Obtain a {@link MongoDatabase} instance to access the database with the given name. * - * @param dbName + * @param dbName must not be {@literal null}. * @return never {@literal null}. * @throws DataAccessException */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index 97d2c7d0ce..aa46fbc882 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -33,7 +33,7 @@ public interface MongoDbFactory extends MongoDatabaseFactory { /** * Creates a default {@link MongoDatabase} instance. * - * @return + * @return never {@literal null}. * @throws DataAccessException * @deprecated since 3.0. Use {@link #getMongoDatabase()} instead. */ @@ -46,7 +46,7 @@ default MongoDatabase getDb() throws DataAccessException { * Obtain a {@link MongoDatabase} instance to access the database with the given name. * * @param dbName must not be {@literal null} or empty. - * @return + * @return never {@literal null}. * @throws DataAccessException * @deprecated since 3.0. Use {@link #getMongoDatabase(String)} instead. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java index d673fd98ce..6a54e94e65 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java @@ -39,7 +39,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { /** * Creates a default {@link MongoDatabase} instance. * - * @return + * @return never {@literal null}. * @throws DataAccessException */ Mono getMongoDatabase() throws DataAccessException; @@ -48,7 +48,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider { * Obtain a {@link MongoDatabase} instance to access the database with the given name. * * @param dbName must not be {@literal null} or empty. - * @return + * @return never {@literal null}. * @throws DataAccessException */ Mono getMongoDatabase(String dbName) throws DataAccessException; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java index 82d9c4fa0a..98bd186da2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java @@ -42,21 +42,21 @@ /** * Configures the {@link AuditorAware} bean to be used to lookup the current principal. * - * @return + * @return empty {@link String} by default. */ String auditorAwareRef() default ""; /** * Configures whether the creation and modification dates are set. Defaults to {@literal true}. * - * @return + * @return {@literal true} by default. */ boolean setDates() default true; /** * Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}. * - * @return + * @return {@literal true} by default. */ boolean modifyOnCreate() default true; @@ -64,7 +64,7 @@ * Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be * used for setting creation and modification dates. * - * @return + * @return empty {@link String} by default. */ String dateTimeProviderRef() default ""; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index e946af8c55..a96617de46 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -95,7 +95,7 @@ public MongoMappingContext mongoMappingContext(MongoCustomConversions customConv /** * Register custom {@link Converter}s in a {@link CustomConversions} object if required. These * {@link CustomConversions} will be registered with the - * {@link org.springframework.data.mongodb.core.convert.MappingMongoConverter} and {@link #mongoMappingContext()}. + * {@link org.springframework.data.mongodb.core.convert.MappingMongoConverter} and {@link MongoMappingContext}. * Returns an empty {@link MongoCustomConversions} instance by default. *

      * NOTE: Use {@link #configureConverters(MongoConverterConfigurationAdapter)} to configure MongoDB diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java index 11b6ff3e0f..bbc85032ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java @@ -94,7 +94,6 @@ enum BulkMode { * Add a list of updates to the bulk operation. For each update request, all matching documents are updated. * * @param updates Update operations to perform. - * @return The bulk operation. * @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}. */ BulkOperations updateMulti(List> updates); @@ -105,7 +104,6 @@ enum BulkMode { * * @param query Update criteria. * @param update Update operation to perform. - * @return The bulk operation. * @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}. */ BulkOperations upsert(Query query, Update update); @@ -115,7 +113,6 @@ enum BulkMode { * else an insert. * * @param updates Updates/insert operations to perform. - * @return The bulk operation. * @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}. */ BulkOperations upsert(List> updates); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java index b5e51613a7..d6b9bcc6e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java @@ -29,7 +29,7 @@ * @author Grame Rocher * @author Oliver Gierke * @author John Brisbin - * @auhtor Christoph Strobl + * @author Christoph Strobl * @since 1.0 */ public interface CollectionCallback { 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 d9338e0f3c..77833c6ada 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 @@ -95,7 +95,7 @@ public static CollectionOptions empty() { /** * Create new {@link CollectionOptions} with already given settings and capped set to {@literal true}.
      - * NOTE Using capped collections requires defining {@link #size(int)}. + * NOTE Using capped collections requires defining {@link #size(long)}. * * @return new {@link CollectionOptions}. * @since 2.0 diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java index a9ce9427cf..bb98bb96bd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java @@ -43,9 +43,10 @@ public interface CursorPreparer extends ReadPreferenceAware { /** * Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor. * - * @param cursor + * @param iterable must not be {@literal null}. + * @return never {@literal null}. */ - FindIterable prepare(FindIterable cursor); + FindIterable prepare(FindIterable iterable); /** * Apply query specific settings to {@link MongoCollection} and initate a find operation returning a @@ -53,7 +54,7 @@ public interface CursorPreparer extends ReadPreferenceAware { * * @param collection must not be {@literal null}. * @param find must not be {@literal null}. - * @return + * @return never {@literal null}. * @throws IllegalArgumentException if one of the required arguments is {@literal null}. * @since 2.2 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java index 1a002392b8..aa97063703 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java @@ -23,7 +23,7 @@ /** * An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document * basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry - * about exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate An + * about exception handling. {@link MongoException}s will be caught and translated by the calling MongoTemplate An * DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for * later inspection. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index 5382b70c0c..a7cbf879ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -66,7 +66,7 @@ class EntityOperations { * Creates a new {@link Entity} for the given bean. * * @param entity must not be {@literal null}. - * @return + * @return new instance of {@link Entity}. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Entity forEntity(T entity) { @@ -89,7 +89,7 @@ public Entity forEntity(T entity) { * * @param entity must not be {@literal null}. * @param conversionService must not be {@literal null}. - * @return + * @return new instance of {@link AdaptibleEntity}. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public AdaptibleEntity forEntity(T entity, ConversionService conversionService) { @@ -108,6 +108,10 @@ public AdaptibleEntity forEntity(T entity, ConversionService conversionSe return AdaptibleMappedEntity.of(entity, context, conversionService); } + /** + * @param entityClass should not be null. + * @return the {@link MongoPersistentEntity#getCollection() collection name}. + */ public String determineCollectionName(@Nullable Class entityClass) { if (entityClass == null) { @@ -138,7 +142,7 @@ public Query getByIdInQuery(Collection entities) { * {@code _id} if no identifier property can be found. * * @param type must not be {@literal null}. - * @return + * @return never {@literal null}. */ public String getIdPropertyName(Class type) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java index 329989818e..4e9bec35e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java @@ -88,9 +88,9 @@ interface TerminatingAggregation { /** * Apply pipeline operations as specified and stream all matching elements.
      - * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.Cursor} + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} * - * @return a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.Cursor} that needs to be closed. + * @return a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to be closed. * Never {@literal null}. */ CloseableIterator stream(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index b2d4e729e5..3bd63bb4f9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -118,7 +118,7 @@ default Optional first() { /** * Stream all matching elements. * - * @return a {@link Stream} that wraps the a Mongo DB {@link com.mongodb.Cursor} that needs to be closed. Never + * @return a {@link Stream} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to be closed. Never * {@literal null}. */ Stream stream(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java index d27fdfac7b..eac01e5298 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java @@ -257,9 +257,9 @@ static class DelegatingQueryCursorPreparer implements CursorPreparer { * @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.clientFindIterable) */ @Override - public FindIterable prepare(FindIterable cursor) { + public FindIterable prepare(FindIterable iterable) { - FindIterable target = delegate != null ? delegate.prepare(cursor) : cursor; + FindIterable target = delegate != null ? delegate.prepare(iterable) : iterable; return limit.map(target::limit).orElse(target); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java index d7fac7ab97..ac8f45d05f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java @@ -78,7 +78,7 @@ public static FindAndModifyOptions none() { } /** - * Create new {@link FindAndModifyOptions} based on option of given {@litearl source}. + * Create new {@link FindAndModifyOptions} based on option of given {@literal source}. * * @param source can be {@literal null}. * @return new instance of {@link FindAndModifyOptions}. @@ -117,8 +117,8 @@ public FindAndModifyOptions remove(boolean remove) { /** * Define the {@link Collation} specifying language-specific rules for string comparison. * - * @param collation - * @return + * @param collation can be {@literal null}. + * @return this. * @since 2.0 */ public FindAndModifyOptions collation(@Nullable Collation collation) { @@ -142,7 +142,7 @@ public boolean isRemove() { /** * Get the {@link Collation} specifying language-specific rules for string comparison. * - * @return + * @return never {@literal null}. * @since 2.0 */ public Optional getCollation() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java index 379015cd8a..2de66015c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java @@ -116,7 +116,7 @@ public FindAndReplaceOptions upsert() { /** * Get the bit indicating to return the replacement document. * - * @return + * @return {@literal true} if set. */ public boolean isReturnNew() { return returnNew; @@ -125,7 +125,7 @@ public boolean isReturnNew() { /** * Get the bit indicating if to create a new document if not exists. * - * @return + * @return {@literal true} if set. */ public boolean isUpsert() { return upsert; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java index ddf1b4e373..3f603f9f48 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java @@ -54,7 +54,7 @@ public interface FindPublisherPreparer extends ReadPreferenceAware { * * @param collection must not be {@literal null}. * @param find must not be {@literal null}. - * @return + * @return never {@literal null}. * @throws IllegalArgumentException if one of the required arguments is {@literal null}. * @since 2.2 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java index ddd1216b3c..0d3b648289 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java @@ -47,7 +47,7 @@ private GeoCommandStatistics(Document source) { * Creates a new {@link GeoCommandStatistics} from the given command result extracting the statistics. * * @param commandResult must not be {@literal null}. - * @return + * @return never {@literal null}. */ public static GeoCommandStatistics from(Document commandResult) { @@ -61,7 +61,7 @@ public static GeoCommandStatistics from(Document commandResult) { * Returns the average distance reported by the command result. Mitigating a removal of the field in case the command * didn't return any result introduced in MongoDB 3.2 RC1. * - * @return + * @return never {@literal null}, uses {@link Double#NaN} if {@literal avgDistance} does not exist. * @see MongoDB Jira SERVER-21024 */ public double getAverageDistance() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 0ec065c2d5..bb6c402fb7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -79,7 +79,7 @@ public interface MongoOperations extends FluentMongoOperations { * The collection name used for the specified class by this template. * * @param entityClass must not be {@literal null}. - * @return + * @return never {@literal null}. */ String getCollectionName(Class entityClass); @@ -363,7 +363,7 @@ public T execute(SessionCallback action, Consumer onComple /** * Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.client.MongoDatabase} level. * - * @return + * @return never {@literal null}. * @since 1.7 * @deprecated since 2.2. The {@code eval} command has been removed without replacement in MongoDB Server 4.2.0. */ @@ -1557,7 +1557,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option /** * Returns the underlying {@link MongoConverter}. * - * @return + * @return never {@literal null}. */ MongoConverter getConverter(); } 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 9d10d4fc0c..b70ddcbb60 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 @@ -3199,9 +3199,9 @@ public QueryCursorPreparer(Query query, @Nullable Class type) { * (non-Javadoc) * @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.DBCursor) */ - public FindIterable prepare(FindIterable cursor) { + public FindIterable prepare(FindIterable iterable) { - FindIterable cursorToUse = cursor; + FindIterable cursorToUse = iterable; operations.forType(type).getCollation(query) // .map(Collation::toMongoCollation) // diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 58d1fa1153..9bf4514b33 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -1239,7 +1239,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific * support.
      * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. @@ -1572,7 +1572,7 @@ Flux mapReduce(Query filterQuery, Class domainType, String inputCollec /** * Returns the underlying {@link MongoConverter}. * - * @return + * @return never {@literal null}. */ MongoConverter getConverter(); @@ -1580,7 +1580,7 @@ Flux mapReduce(Query filterQuery, Class domainType, String inputCollec * The collection name used for the specified class by this template. * * @param entityClass must not be {@literal null}. - * @return + * @return never {@literal null}. * @since 2.1 */ String getCollectionName(Class entityClass); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 67eec65940..9bfcc533f7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -319,8 +319,7 @@ public void setWriteResultChecking(@Nullable WriteResultChecking resultChecking) /** * Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern} - * configured on the {@link MongoDatabaseFactory} will apply. If you configured a {@link Mongo} instance no - * {@link WriteConcern} will be used. + * configured on the {@link MongoDatabaseFactory} will apply. * * @param writeConcern can be {@literal null}. */ @@ -2411,7 +2410,7 @@ protected Flux doFind(String collectionName, Document query, Document fie * @param query the query document that specifies the criteria used to find a record. * @param fields the document that specifies the fields to be returned. * @param entityClass the parameterized type of the returned list. - * @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply + * @param preparer allows for customization of the {@link com.mongodb.client.FindIterable} used when iterating over the result set, (apply * limits, skips and so on). * @return the {@link List} of converted objects. */ @@ -2842,7 +2841,7 @@ private Document getMappedSortObject(Query query, Class type) { /** * Simple {@link ReactiveCollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Oliver Gierke * @author Thomas Risberg diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java index ceffe9e8d5..3183bf92ba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java @@ -16,8 +16,8 @@ package org.springframework.data.mongodb.core; /** - * Enum to represent how strict the check of {@link com.mongodb.WriteResult} shall be. It can either be skipped entirely - * (use {@link #NONE}) or cause an exception to be thrown {@link #EXCEPTION}. + * Enum to represent how strict the check of {@link com.mongodb.WriteConcernResult} shall be. It can either be skipped + * entirely (use {@link #NONE}) or cause an exception to be thrown {@link #EXCEPTION}. * * @author Thomas Risberg * @author Oliver Gierke diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java index d1a7c01a15..c9a5a73c3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java @@ -34,7 +34,7 @@ public class AccumulatorOperators { * Take the numeric value referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link AccumulatorOperatorFactory}. */ public static AccumulatorOperatorFactory valueOf(String fieldReference) { return new AccumulatorOperatorFactory(fieldReference); @@ -44,7 +44,7 @@ public static AccumulatorOperatorFactory valueOf(String fieldReference) { * Take the numeric value referenced resulting from given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link AccumulatorOperatorFactory}. */ public static AccumulatorOperatorFactory valueOf(AggregationExpression expression) { return new AccumulatorOperatorFactory(expression); @@ -86,7 +86,7 @@ public AccumulatorOperatorFactory(AggregationExpression expression) { * Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates and * returns the sum. * - * @return + * @return new instance of {@link Sum}. */ public Sum sum() { return usesFieldRef() ? Sum.sumOf(fieldReference) : Sum.sumOf(expression); @@ -96,7 +96,7 @@ public Sum sum() { * Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the * average value. * - * @return + * @return new instance of {@link Avg}. */ public Avg avg() { return usesFieldRef() ? Avg.avgOf(fieldReference) : Avg.avgOf(expression); @@ -106,7 +106,7 @@ public Avg avg() { * Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the * maximum value. * - * @return + * @return new instance of {@link Max}. */ public Max max() { return usesFieldRef() ? Max.maxOf(fieldReference) : Max.maxOf(expression); @@ -116,7 +116,7 @@ public Max max() { * Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the * minimum value. * - * @return + * @return new instance of {@link Min}. */ public Min min() { return usesFieldRef() ? Min.minOf(fieldReference) : Min.minOf(expression); @@ -126,7 +126,7 @@ public Min min() { * Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates the * population standard deviation of the input values. * - * @return + * @return new instance of {@link StdDevPop}. */ public StdDevPop stdDevPop() { return usesFieldRef() ? StdDevPop.stdDevPopOf(fieldReference) : StdDevPop.stdDevPopOf(expression); @@ -136,7 +136,7 @@ public StdDevPop stdDevPop() { * Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates the * sample standard deviation of the input values. * - * @return + * @return new instance of {@link StdDevSamp}. */ public StdDevSamp stdDevSamp() { return usesFieldRef() ? StdDevSamp.stdDevSampOf(fieldReference) : StdDevSamp.stdDevSampOf(expression); @@ -167,7 +167,7 @@ protected String getMongoMethod() { * Creates new {@link Sum}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Sum}. */ public static Sum sumOf(String fieldReference) { @@ -179,7 +179,7 @@ public static Sum sumOf(String fieldReference) { * Creates new {@link Sum}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Sum}. */ public static Sum sumOf(AggregationExpression expression) { @@ -192,7 +192,7 @@ public static Sum sumOf(AggregationExpression expression) { * NOTE: Only possible in {@code $project} stage. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Sum}. */ public Sum and(String fieldReference) { @@ -205,7 +205,7 @@ public Sum and(String fieldReference) { * NOTE: Only possible in {@code $project} stage. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Sum}. */ public Sum and(AggregationExpression expression) { @@ -264,7 +264,7 @@ protected String getMongoMethod() { * Creates new {@link Avg}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Avg}. */ public static Avg avgOf(String fieldReference) { @@ -276,7 +276,7 @@ public static Avg avgOf(String fieldReference) { * Creates new {@link Avg}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Avg}. */ public static Avg avgOf(AggregationExpression expression) { @@ -289,7 +289,7 @@ public static Avg avgOf(AggregationExpression expression) { * NOTE: Only possible in {@code $project} stage. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Avg}. */ public Avg and(String fieldReference) { @@ -302,7 +302,7 @@ public Avg and(String fieldReference) { * NOTE: Only possible in {@code $project} stage. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Avg}. */ public Avg and(AggregationExpression expression) { @@ -347,7 +347,7 @@ protected String getMongoMethod() { * Creates new {@link Max}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Max}. */ public static Max maxOf(String fieldReference) { @@ -359,7 +359,7 @@ public static Max maxOf(String fieldReference) { * Creates new {@link Max}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Max}. */ public static Max maxOf(AggregationExpression expression) { @@ -372,7 +372,7 @@ public static Max maxOf(AggregationExpression expression) { * NOTE: Only possible in {@code $project} stage. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Max}. */ public Max and(String fieldReference) { @@ -385,7 +385,7 @@ public Max and(String fieldReference) { * NOTE: Only possible in {@code $project} stage. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Max}. */ public Max and(AggregationExpression expression) { @@ -430,7 +430,7 @@ protected String getMongoMethod() { * Creates new {@link Min}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Min}. */ public static Min minOf(String fieldReference) { @@ -442,7 +442,7 @@ public static Min minOf(String fieldReference) { * Creates new {@link Min}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Min}. */ public static Min minOf(AggregationExpression expression) { @@ -455,7 +455,7 @@ public static Min minOf(AggregationExpression expression) { * NOTE: Only possible in {@code $project} stage. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Min}. */ public Min and(String fieldReference) { @@ -468,7 +468,7 @@ public Min and(String fieldReference) { * NOTE: Only possible in {@code $project} stage. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Min}. */ public Min and(AggregationExpression expression) { @@ -513,7 +513,7 @@ protected String getMongoMethod() { * Creates new {@link StdDevPop}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StdDevPop}. */ public static StdDevPop stdDevPopOf(String fieldReference) { @@ -525,7 +525,7 @@ public static StdDevPop stdDevPopOf(String fieldReference) { * Creates new {@link StdDevPop} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StdDevPop}. */ public static StdDevPop stdDevPopOf(AggregationExpression expression) { @@ -538,7 +538,7 @@ public static StdDevPop stdDevPopOf(AggregationExpression expression) { * NOTE: Only possible in {@code $project} stage. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StdDevPop}. */ public StdDevPop and(String fieldReference) { @@ -551,7 +551,7 @@ public StdDevPop and(String fieldReference) { * NOTE: Only possible in {@code $project} stage. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StdDevPop}. */ public StdDevPop and(AggregationExpression expression) { @@ -596,7 +596,7 @@ protected String getMongoMethod() { * Creates new {@link StdDevSamp}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StdDevSamp}. */ public static StdDevSamp stdDevSampOf(String fieldReference) { @@ -608,7 +608,7 @@ public static StdDevSamp stdDevSampOf(String fieldReference) { * Creates new {@link StdDevSamp}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StdDevSamp}. */ public static StdDevSamp stdDevSampOf(AggregationExpression expression) { @@ -621,7 +621,7 @@ public static StdDevSamp stdDevSampOf(AggregationExpression expression) { * NOTE: Only possible in {@code $project} stage. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StdDevSamp}. */ public StdDevSamp and(String fieldReference) { @@ -634,7 +634,7 @@ public StdDevSamp and(String fieldReference) { * NOTE: Only possible in {@code $project} stage. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StdDevSamp}. */ public StdDevSamp and(AggregationExpression expression) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 8a29c0dfc4..9128977411 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -133,7 +133,7 @@ public static AggregationUpdate newUpdate(AggregationOperation... operations) { * supported in MongoDB version 2.6+. * * @param options must not be {@literal null}. - * @return + * @return new instance of {@link Aggregation}. * @since 1.6 */ public Aggregation withOptions(AggregationOptions options) { @@ -259,7 +259,7 @@ public static AddFieldsOperationBuilder addFields() { * Creates a new {@link ProjectionOperation} including the given fields. * * @param fields must not be {@literal null}. - * @return + * @return new instance of {@link ProjectionOperation}. */ public static ProjectionOperation project(String... fields) { return project(fields(fields)); @@ -269,7 +269,7 @@ public static ProjectionOperation project(String... fields) { * Creates a new {@link ProjectionOperation} including the given {@link Fields}. * * @param fields must not be {@literal null}. - * @return + * @return new instance of {@link ProjectionOperation}. */ public static ProjectionOperation project(Fields fields) { return new ProjectionOperation(fields); @@ -292,7 +292,7 @@ public static ProjectionOperation project(Class type) { * Factory method to create a new {@link UnwindOperation} for the field with the given name. * * @param field must not be {@literal null} or empty. - * @return + * @return new instance of {@link UnwindOperation}. */ public static UnwindOperation unwind(String field) { return new UnwindOperation(field(field)); @@ -302,7 +302,7 @@ public static UnwindOperation unwind(String field) { * Factory method to create a new {@link ReplaceRootOperation} for the field with the given name. * * @param fieldName must not be {@literal null} or empty. - * @return + * @return new instance of {@link ReplaceRootOperation}. * @since 1.10 */ public static ReplaceRootOperation replaceRoot(String fieldName) { @@ -314,7 +314,7 @@ public static ReplaceRootOperation replaceRoot(String fieldName) { * {@link AggregationExpression}. * * @param aggregationExpression must not be {@literal null}. - * @return + * @return new instance of {@link ReplaceRootOperation}. * @since 1.10 */ public static ReplaceRootOperation replaceRoot(AggregationExpression aggregationExpression) { @@ -380,7 +380,7 @@ public static UnwindOperation unwind(String field, String arrayIndex, boolean pr * Creates a new {@link GroupOperation} for the given fields. * * @param fields must not be {@literal null}. - * @return + * @return new instance of {@link GroupOperation}. */ public static GroupOperation group(String... fields) { return group(fields(fields)); @@ -401,7 +401,7 @@ public static GroupOperation group(Fields fields) { * {@link GraphLookupOperation} given {@literal fromCollection}. * * @param fromCollection must not be {@literal null} or empty. - * @return + * @return new instance of {@link StartWithBuilder} for creating a {@link GraphLookupOperation}. * @since 1.10 */ public static StartWithBuilder graphLookup(String fromCollection) { @@ -412,7 +412,7 @@ public static StartWithBuilder graphLookup(String fromCollection) { * Factory method to create a new {@link SortOperation} for the given {@link Sort}. * * @param sort must not be {@literal null}. - * @return + * @return new instance of {@link SortOperation}. */ public static SortOperation sort(Sort sort) { return new SortOperation(sort); @@ -423,7 +423,7 @@ public static SortOperation sort(Sort sort) { * * @param direction must not be {@literal null}. * @param fields must not be {@literal null}. - * @return + * @return new instance of {@link SortOperation}. */ public static SortOperation sort(Direction direction, String... fields) { return new SortOperation(Sort.by(direction, fields)); @@ -433,7 +433,7 @@ public static SortOperation sort(Direction direction, String... fields) { * Creates a new {@link SortByCountOperation} given {@literal groupByField}. * * @param field must not be {@literal null} or empty. - * @return + * @return new instance of {@link SortByCountOperation}. * @since 2.1 */ public static SortByCountOperation sortByCount(String field) { @@ -444,7 +444,7 @@ public static SortByCountOperation sortByCount(String field) { * Creates a new {@link SortByCountOperation} given {@link AggregationExpression group and sort expression}. * * @param groupAndSortExpression must not be {@literal null}. - * @return + * @return new instance of {@link SortByCountOperation}. * @since 2.1 */ public static SortByCountOperation sortByCount(AggregationExpression groupAndSortExpression) { @@ -455,9 +455,10 @@ public static SortByCountOperation sortByCount(AggregationExpression groupAndSor * Creates a new {@link SkipOperation} skipping the given number of elements. * * @param elementsToSkip must not be less than zero. - * @return + * @return new instance of {@link SkipOperation}. * @deprecated prepare to get this one removed in favor of {@link #skip(long)}. */ + @Deprecated public static SkipOperation skip(int elementsToSkip) { return new SkipOperation(elementsToSkip); } @@ -466,7 +467,7 @@ public static SkipOperation skip(int elementsToSkip) { * Creates a new {@link SkipOperation} skipping the given number of elements. * * @param elementsToSkip must not be less than zero. - * @return + * @return new instance of {@link SkipOperation}. */ public static SkipOperation skip(long elementsToSkip) { return new SkipOperation(elementsToSkip); @@ -476,7 +477,7 @@ public static SkipOperation skip(long elementsToSkip) { * Creates a new {@link LimitOperation} limiting the result to the given number of elements. * * @param maxElements must not be less than zero. - * @return + * @return new instance of {@link LimitOperation}. */ public static LimitOperation limit(long maxElements) { return new LimitOperation(maxElements); @@ -486,7 +487,7 @@ public static LimitOperation limit(long maxElements) { * Creates a new {@link SampleOperation} to select the specified number of documents from its input randomly. * * @param sampleSize must not be less than zero. - * @return + * @return new instance of {@link SampleOperation}. * @since 2.0 */ public static SampleOperation sample(long sampleSize) { @@ -497,7 +498,7 @@ public static SampleOperation sample(long sampleSize) { * Creates a new {@link MatchOperation} using the given {@link Criteria}. * * @param criteria must not be {@literal null}. - * @return + * @return new instance of {@link MatchOperation}. */ public static MatchOperation match(Criteria criteria) { return new MatchOperation(criteria); @@ -507,7 +508,7 @@ public static MatchOperation match(Criteria criteria) { * Creates a new {@link MatchOperation} using the given {@link CriteriaDefinition}. * * @param criteria must not be {@literal null}. - * @return + * @return new instance of {@link MatchOperation}. * @since 1.10 */ public static MatchOperation match(CriteriaDefinition criteria) { @@ -520,7 +521,7 @@ public static MatchOperation match(CriteriaDefinition criteria) { * * @param query must not be {@literal null}. * @param distanceField must not be {@literal null} or empty. - * @return + * @return new instance of {@link GeoNearOperation}. * @since 1.7 */ public static GeoNearOperation geoNear(NearQuery query, String distanceField) { @@ -546,7 +547,7 @@ public static MergeOperationBuilder merge() { * collection in the current database if one does not already exist. The collection is not visible until the * aggregation completes. If the aggregation fails, MongoDB does not create the collection. Must not be * {@literal null}. - * @return + * @return new instance of {@link OutOperation}. */ public static OutOperation out(String outCollectionName) { return new OutOperation(outCollectionName); @@ -556,7 +557,7 @@ public static OutOperation out(String outCollectionName) { * Creates a new {@link BucketOperation} given {@literal groupByField}. * * @param groupByField must not be {@literal null} or empty. - * @return + * @return new instance of {@link BucketOperation}. * @since 1.10 */ public static BucketOperation bucket(String groupByField) { @@ -567,7 +568,7 @@ public static BucketOperation bucket(String groupByField) { * Creates a new {@link BucketOperation} given {@link AggregationExpression group-by expression}. * * @param groupByExpression must not be {@literal null}. - * @return + * @return new instance of {@link BucketOperation}. * @since 1.10 */ public static BucketOperation bucket(AggregationExpression groupByExpression) { @@ -579,7 +580,7 @@ public static BucketOperation bucket(AggregationExpression groupByExpression) { * * @param groupByField must not be {@literal null} or empty. * @param buckets number of buckets, must be a positive integer. - * @return + * @return new instance of {@link BucketAutoOperation}. * @since 1.10 */ public static BucketAutoOperation bucketAuto(String groupByField, int buckets) { @@ -591,7 +592,7 @@ public static BucketAutoOperation bucketAuto(String groupByField, int buckets) { * * @param groupByExpression must not be {@literal null}. * @param buckets number of buckets, must be a positive integer. - * @return + * @return new instance of {@link BucketAutoOperation}. * @since 1.10 */ public static BucketAutoOperation bucketAuto(AggregationExpression groupByExpression, int buckets) { @@ -601,7 +602,7 @@ public static BucketAutoOperation bucketAuto(AggregationExpression groupByExpres /** * Creates a new {@link FacetOperation}. * - * @return + * @return new instance of {@link FacetOperation}. * @since 1.10 */ public static FacetOperation facet() { @@ -612,7 +613,7 @@ public static FacetOperation facet() { * Creates a new {@link FacetOperationBuilder} given {@link Aggregation}. * * @param aggregationOperations the sub-pipeline, must not be {@literal null}. - * @return + * @return new instance of {@link FacetOperation}. * @since 1.10 */ public static FacetOperationBuilder facet(AggregationOperation... aggregationOperations) { @@ -681,7 +682,7 @@ public static RedactOperation redact(AggregationExpression condition) { * Creates a new {@link Fields} instance for the given field names. * * @param fields must not be {@literal null}. - * @return + * @return new instance of {@link Fields}. * @see Fields#fields(String...) */ public static Fields fields(String... fields) { @@ -693,7 +694,7 @@ public static Fields fields(String... fields) { * * @param name must not be {@literal null} or empty. * @param target must not be {@literal null} or empty. - * @return + * @return new instance of {@link Fields}. */ public static Fields bind(String name, String target) { return Fields.from(field(name, target)); @@ -702,7 +703,7 @@ public static Fields bind(String name, String target) { /** * Returns a new {@link AggregationOptions.Builder}. * - * @return + * @return new instance of {@link AggregationOptions.Builder}. * @since 1.6 */ public static AggregationOptions.Builder newAggregationOptions() { @@ -764,7 +765,7 @@ enum SystemVariable { * otherwise. * * @param fieldRef may be {@literal null}. - * @return + * @return {@literal true} if the given field refers to a {@link SystemVariable}. */ public static boolean isReferingToSystemVariable(@Nullable String fieldRef) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java index 5fb2e8278d..7e15a70284 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java @@ -31,8 +31,8 @@ public interface AggregationExpression { * Turns the {@link AggregationExpression} into a {@link Document} within the given * {@link AggregationOperationContext}. * - * @param context - * @return + * @param context must not be {@literal null}. + * @return the MongoDB native ({@link Document}) form of the expression. */ Document toDocument(AggregationOperationContext context); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java index a89905e668..635f00abec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java @@ -53,7 +53,7 @@ class AggregationExpressionTransformationContext * @param currentNode must not be {@literal null}. * @param parentNode may be {@literal null}. * @param previousOperationObject may be {@literal null}. - * @param aggregationContext must not be {@literal null}. + * @param context must not be {@literal null}. */ public AggregationExpressionTransformationContext(T currentNode, @Nullable ExpressionNode parentNode, @Nullable Document previousOperationObject, AggregationOperationContext context) { @@ -67,7 +67,7 @@ public AggregationExpressionTransformationContext(T currentNode, @Nullable Expre /** * Returns the underlying {@link AggregationOperationContext}. * - * @return + * @return never {@literal null}. */ public AggregationOperationContext getAggregationContext() { return aggregationContext; @@ -76,7 +76,7 @@ public AggregationOperationContext getAggregationContext() { /** * Returns the {@link FieldReference} for the current {@link ExpressionNode}. * - * @return + * @return never {@literal null}. */ public FieldReference getFieldReference() { return aggregationContext.getReference(getCurrentNode().getName()); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java index 28e8b63f61..4c7f687663 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java @@ -41,7 +41,7 @@ public enum AggregationFunctionExpressions { * Returns an {@link AggregationExpression} build from the current {@link Enum} name and the given parameters. * * @param parameters must not be {@literal null} - * @return + * @return new instance of {@link AggregationExpression}. */ public AggregationExpression of(Object... parameters) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java index 6862cf5156..b86407edbb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java @@ -57,20 +57,20 @@ default Document getMappedObject(Document document) { Document getMappedObject(Document document, @Nullable Class type); /** - * Returns a {@link FieldReference} for the given field or {@literal null} if the context does not expose the given - * field. + * Returns a {@link FieldReference} for the given field. * * @param field must not be {@literal null}. - * @return + * @return the {@link FieldReference} for the given {@link Field}. + * @throws IllegalArgumentException if the context does not expose a field with the given name */ FieldReference getReference(Field field); /** - * Returns the {@link FieldReference} for the field with the given name or {@literal null} if the context does not - * expose a field with the given name. + * Returns the {@link FieldReference} for the field with the given name. * * @param name must not be {@literal null} or empty. - * @return + * @return the {@link FieldReference} for the field with given {@literal name}. + * @throws IllegalArgumentException if the context does not expose a field with the given name */ FieldReference getReference(String name); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 5be87b5733..96b199b8c0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -70,7 +70,7 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, Document cursor * @param allowDiskUse whether to off-load intensive sort-operations to disk. * @param explain whether to get the execution plan for the aggregation instead of the actual results. * @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the - * aggregation. + * aggregation. * @param collation collation for string comparison. Can be {@literal null}. * @since 2.0 */ @@ -85,7 +85,7 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Docum * @param allowDiskUse whether to off-load intensive sort-operations to disk. * @param explain whether to get the execution plan for the aggregation instead of the actual results. * @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the - * aggregation. + * aggregation. * @param collation collation for string comparison. Can be {@literal null}. * @param comment execution comment. Can be {@literal null}. * @since 2.2 @@ -151,7 +151,7 @@ public static Builder builder() { * Enables writing to temporary files. When set to true, aggregation stages can write data to the _tmp subdirectory in * the dbPath directory. * - * @return + * @return {@literal true} if enabled. */ public boolean isAllowDiskUse() { return allowDiskUse; @@ -160,7 +160,7 @@ public boolean isAllowDiskUse() { /** * Specifies to return the information on the processing of the pipeline. * - * @return + * @return {@literal true} if enabled. */ public boolean isExplain() { return explain; @@ -185,7 +185,7 @@ public Integer getCursorBatchSize() { /** * Specify a document that contains options that control the creation of the cursor object. * - * @return + * @return never {@literal null}. */ public Optional getCursor() { return cursor; @@ -194,7 +194,7 @@ public Optional getCursor() { /** * Get collation settings for string comparison. * - * @return + * @return never {@literal null}. * @since 2.0 */ public Optional getCollation() { @@ -204,7 +204,7 @@ public Optional getCollation() { /** * Get the comment for the aggregation. * - * @return + * @return never {@literal null}. * @since 2.2 */ public Optional getComment() { @@ -256,7 +256,7 @@ Document applyAndReturnPotentiallyChangedCommand(Document command) { /** * Returns a {@link Document} representation of this {@link AggregationOptions}. * - * @return + * @return never {@literal null}. */ public Document toDocument() { @@ -276,7 +276,7 @@ public Document toDocument() { } /** - * @return + * @return {@literal true} if {@link #maxTime} is set to a positive value. * @since 3.0 */ public boolean hasExecutionTimeLimit() { @@ -313,8 +313,8 @@ public static class Builder { /** * Defines whether to off-load intensive sort-operations to disk. * - * @param allowDiskUse - * @return + * @param allowDiskUse use {@literal true} to allow disk use during the aggregation. + * @return this. */ public Builder allowDiskUse(boolean allowDiskUse) { @@ -325,8 +325,8 @@ public Builder allowDiskUse(boolean allowDiskUse) { /** * Defines whether to get the execution plan for the aggregation instead of the actual results. * - * @param explain - * @return + * @param explain use {@literal true} to enable explain feature. + * @return this. */ public Builder explain(boolean explain) { @@ -337,8 +337,8 @@ public Builder explain(boolean explain) { /** * Additional options to the aggregation. * - * @param cursor - * @return + * @param cursor must not be {@literal null}. + * @return this. */ public Builder cursor(Document cursor) { @@ -349,8 +349,8 @@ public Builder cursor(Document cursor) { /** * Define the initial cursor batch size. * - * @param batchSize - * @return + * @param batchSize use a positive int. + * @return this. * @since 2.0 */ public Builder cursorBatchSize(int batchSize) { @@ -363,7 +363,7 @@ public Builder cursorBatchSize(int batchSize) { * Define collation settings for string comparison. * * @param collation can be {@literal null}. - * @return + * @return this. * @since 2.0 */ public Builder collation(@Nullable Collation collation) { @@ -376,7 +376,7 @@ public Builder collation(@Nullable Collation collation) { * Define a comment to describe the execution. * * @param comment can be {@literal null}. - * @return + * @return this. * @since 2.2 */ public Builder comment(@Nullable String comment) { @@ -389,7 +389,7 @@ public Builder comment(@Nullable String comment) { * Set the time limit for processing. * * @param maxTime {@link Duration#ZERO} is used for the default unbounded behavior. {@link Duration#isNegative() - * Negative} values will be ignored. + * Negative} values will be ignored. * @return this. * @since 3.0 */ @@ -402,7 +402,7 @@ public Builder maxTime(@Nullable Duration maxTime) { /** * Returns a new {@link AggregationOptions} instance with the given configuration. * - * @return + * @return new instance of {@link AggregationOptions}. */ public AggregationOptions build() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java index 2e6cd72575..fd14b1a0b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java @@ -59,7 +59,7 @@ public AggregationResults(List mappedResults, Document rawResults) { /** * Returns the aggregation results. * - * @return + * @return the list of already mapped results or an empty one if none found. */ public List getMappedResults() { return mappedResults; @@ -68,7 +68,7 @@ public List getMappedResults() { /** * Returns the unique mapped result. Assumes no result or exactly one. * - * @return + * @return the single already mapped result object or raise an error if more than one found. * @throws IllegalArgumentException in case more than one result is available. */ @Nullable @@ -88,7 +88,7 @@ public Iterator iterator() { /** * Returns the server that has been used to perform the aggregation. * - * @return + * @return can be {@literal null}. */ @Nullable public String getServerUsed() { @@ -98,7 +98,7 @@ public String getServerUsed() { /** * Returns the raw result that was returned by the server. * - * @return + * @return the raw response. * @since 1.6 */ public Document getRawResults() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java index 23bb50e364..0556410c89 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java @@ -56,7 +56,7 @@ private AggregationSpELExpression(String rawExpression, Object[] parameters) { * * @param expressionString must not be {@literal null}. * @param parameters can be empty. - * @return + * @return new instance of {@link AggregationSpELExpression}. */ public static AggregationSpELExpression expressionOf(String expressionString, Object... parameters) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index c97ca3974b..e5dadc8412 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -164,7 +164,7 @@ public AggregationUpdate unset(UnsetOperation unsetOperation) { * {@code $replaceWith} replaces the input document with the specified document. The operation replaces all existing * fields in the input document, including the _id field. * - * @param replaceWithOperation + * @param replaceWithOperation must not be {@literal null}. * @return this. * @see $replaceWith Aggregation * Reference @@ -219,8 +219,8 @@ public AggregationUpdate toValueOf(Object value) { /** * Short for {@link #unset(UnsetOperation)}. * - * @param keys - * @return + * @param keys the fields to remove. + * @return this. */ public AggregationUpdate unset(String... keys) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java index ae5b959fbd..d729b9dfaf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java @@ -32,9 +32,9 @@ interface AggregationUtils { * Converts the given {@link Range} into an array of values. * * @param range must not be {@literal null}. - * @return + * @return never {@literal null}. */ - public static List toRangeValues(Range range) { + static List toRangeValues(Range range) { Assert.notNull(range, "Range must not be null!"); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 9cda3ffcda..2fbc64304e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -38,7 +38,7 @@ public class ArithmeticOperators { * Take the field referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ArithmeticOperatorFactory}. */ public static ArithmeticOperatorFactory valueOf(String fieldReference) { return new ArithmeticOperatorFactory(fieldReference); @@ -48,7 +48,7 @@ public static ArithmeticOperatorFactory valueOf(String fieldReference) { * Take the value resulting from the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ArithmeticOperatorFactory}. */ public static ArithmeticOperatorFactory valueOf(AggregationExpression expression) { return new ArithmeticOperatorFactory(expression); @@ -89,7 +89,7 @@ public ArithmeticOperatorFactory(AggregationExpression expression) { /** * Creates new {@link AggregationExpression} that returns the absolute value of the associated number. * - * @return + * @return new instance of {@link Abs}. */ public Abs abs() { return usesFieldRef() ? Abs.absoluteValueOf(fieldReference) : Abs.absoluteValueOf(expression); @@ -100,7 +100,7 @@ public Abs abs() { * number. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Add}. */ public Add add(String fieldReference) { @@ -113,7 +113,7 @@ public Add add(String fieldReference) { * {@link AggregationExpression} to the associated number. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Add}. */ public Add add(AggregationExpression expression) { @@ -125,7 +125,7 @@ public Add add(AggregationExpression expression) { * Creates new {@link AggregationExpression} that adds the given {@literal value} to the associated number. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Add}. */ public Add add(Number value) { @@ -141,7 +141,7 @@ private Add createAdd() { * Creates new {@link AggregationExpression} that returns the smallest integer greater than or equal to the * assoicated number. * - * @return + * @return new instance of {@link Ceil}. */ public Ceil ceil() { return usesFieldRef() ? Ceil.ceilValueOf(fieldReference) : Ceil.ceilValueOf(expression); @@ -152,7 +152,7 @@ public Ceil ceil() { * {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Divide}. */ public Divide divideBy(String fieldReference) { @@ -165,7 +165,7 @@ public Divide divideBy(String fieldReference) { * {@literal expression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Divide}. */ public Divide divideBy(AggregationExpression expression) { @@ -176,8 +176,8 @@ public Divide divideBy(AggregationExpression expression) { /** * Creates new {@link AggregationExpression} that divides the associated number by given {@literal value}. * - * @param value - * @return + * @param value must not be {@literal null}. + * @return new instance of {@link Divide}. */ public Divide divideBy(Number value) { @@ -192,7 +192,7 @@ private Divide createDivide() { /** * Creates new {@link AggregationExpression} that raises Euler’s number (i.e. e ) on the associated number. * - * @return + * @return new instance of {@link Exp}. */ public Exp exp() { return usesFieldRef() ? Exp.expValueOf(fieldReference) : Exp.expValueOf(expression); @@ -202,7 +202,7 @@ public Exp exp() { * Creates new {@link AggregationExpression} that returns the largest integer less than or equal to the associated * number. * - * @return + * @return new instance of {@link Floor}. */ public Floor floor() { return usesFieldRef() ? Floor.floorValueOf(fieldReference) : Floor.floorValueOf(expression); @@ -212,7 +212,7 @@ public Floor floor() { * Creates new {@link AggregationExpression} that calculates the natural logarithm ln (i.e loge) of the assoicated * number. * - * @return + * @return new instance of {@link Ln}. */ public Ln ln() { return usesFieldRef() ? Ln.lnValueOf(fieldReference) : Ln.lnValueOf(expression); @@ -223,7 +223,7 @@ public Ln ln() { * referenced via {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Log}. */ public Log log(String fieldReference) { @@ -236,7 +236,7 @@ public Log log(String fieldReference) { * extracted by given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Log}. */ public Log log(AggregationExpression expression) { @@ -249,7 +249,7 @@ public Log log(AggregationExpression expression) { * {@literal base}. * * @param base must not be {@literal null}. - * @return + * @return new instance of {@link Log}. */ public Log log(Number base) { @@ -264,7 +264,7 @@ private Log createLog() { /** * Creates new {@link AggregationExpression} that calculates the log base 10 for the associated number. * - * @return + * @return new instance of {@link Log10}. */ public Log10 log10() { return usesFieldRef() ? Log10.log10ValueOf(fieldReference) : Log10.log10ValueOf(expression); @@ -275,7 +275,7 @@ public Log10 log10() { * remainder. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Mod}. */ public Mod mod(String fieldReference) { @@ -288,7 +288,7 @@ public Mod mod(String fieldReference) { * remainder. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Mod}. */ public Mod mod(AggregationExpression expression) { @@ -301,7 +301,7 @@ public Mod mod(AggregationExpression expression) { * remainder. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Mod}. */ public Mod mod(Number value) { @@ -317,7 +317,7 @@ private Mod createMod() { * Creates new {@link AggregationExpression} that multiplies the associated number with another. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Multiply}. */ public Multiply multiplyBy(String fieldReference) { @@ -329,7 +329,7 @@ public Multiply multiplyBy(String fieldReference) { * Creates new {@link AggregationExpression} that multiplies the associated number with another. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Multiply}. */ public Multiply multiplyBy(AggregationExpression expression) { @@ -341,7 +341,7 @@ public Multiply multiplyBy(AggregationExpression expression) { * Creates new {@link AggregationExpression} that multiplies the associated number with another. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Multiply}. */ public Multiply multiplyBy(Number value) { @@ -357,7 +357,7 @@ private Multiply createMultiply() { * Creates new {@link AggregationExpression} that raises the associated number to the specified exponent. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Pow}. */ public Pow pow(String fieldReference) { @@ -369,7 +369,7 @@ public Pow pow(String fieldReference) { * Creates new {@link AggregationExpression} that raises the associated number to the specified exponent. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Pow}. */ public Pow pow(AggregationExpression expression) { @@ -381,7 +381,7 @@ public Pow pow(AggregationExpression expression) { * Creates new {@link AggregationExpression} that raises the associated number to the specified exponent. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Pow}. */ public Pow pow(Number value) { @@ -396,7 +396,7 @@ private Pow createPow() { /** * Creates new {@link AggregationExpression} that calculates the square root of the associated number. * - * @return + * @return new instance of {@link Sqrt}. */ public Sqrt sqrt() { return usesFieldRef() ? Sqrt.sqrtOf(fieldReference) : Sqrt.sqrtOf(expression); @@ -406,7 +406,7 @@ public Sqrt sqrt() { * Creates new {@link AggregationExpression} that subtracts value of given from the associated number. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Subtract}. */ public Subtract subtract(String fieldReference) { @@ -418,7 +418,7 @@ public Subtract subtract(String fieldReference) { * Creates new {@link AggregationExpression} that subtracts value of given from the associated number. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Subtract}. */ public Subtract subtract(AggregationExpression expression) { @@ -429,8 +429,8 @@ public Subtract subtract(AggregationExpression expression) { /** * Creates new {@link AggregationExpression} that subtracts value from the associated number. * - * @param value - * @return + * @param value must not be {@literal null}. + * @return new instance of {@link Subtract}. */ public Subtract subtract(Number value) { @@ -445,7 +445,7 @@ private Subtract createSubtract() { /** * Creates new {@link AggregationExpression} that truncates a number to its integer. * - * @return + * @return new instance of {@link Trunc}. */ public Trunc trunc() { return usesFieldRef() ? Trunc.truncValueOf(fieldReference) : Trunc.truncValueOf(expression); @@ -454,7 +454,7 @@ public Trunc trunc() { /** * Creates new {@link AggregationExpression} that calculates and returns the sum of numeric values. * - * @return + * @return new instance of {@link Sum}. */ public Sum sum() { return usesFieldRef() ? AccumulatorOperators.Sum.sumOf(fieldReference) @@ -464,7 +464,7 @@ public Sum sum() { /** * Creates new {@link AggregationExpression} that returns the average value of the numeric values. * - * @return + * @return new instance of {@link Avg}. */ public Avg avg() { return usesFieldRef() ? AccumulatorOperators.Avg.avgOf(fieldReference) @@ -474,7 +474,7 @@ public Avg avg() { /** * Creates new {@link AggregationExpression} that returns the maximum value. * - * @return + * @return new instance of {@link Max}. */ public Max max() { return usesFieldRef() ? AccumulatorOperators.Max.maxOf(fieldReference) @@ -484,7 +484,7 @@ public Max max() { /** * Creates new {@link AggregationExpression} that returns the minimum value. * - * @return + * @return new instance of {@link Min}. */ public Min min() { return usesFieldRef() ? AccumulatorOperators.Min.minOf(fieldReference) @@ -494,7 +494,7 @@ public Min min() { /** * Creates new {@link AggregationExpression} that calculates the population standard deviation of the input values. * - * @return + * @return new instance of {@link StdDevPop}. */ public StdDevPop stdDevPop() { return usesFieldRef() ? AccumulatorOperators.StdDevPop.stdDevPopOf(fieldReference) @@ -504,7 +504,7 @@ public StdDevPop stdDevPop() { /** * Creates new {@link AggregationExpression} that calculates the sample standard deviation of the input values. * - * @return + * @return new instance of {@link StdDevSamp}. */ public StdDevSamp stdDevSamp() { return usesFieldRef() ? AccumulatorOperators.StdDevSamp.stdDevSampOf(fieldReference) @@ -557,7 +557,7 @@ protected String getMongoMethod() { * Creates new {@link Abs}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Abs}. */ public static Abs absoluteValueOf(String fieldReference) { @@ -569,7 +569,7 @@ public static Abs absoluteValueOf(String fieldReference) { * Creates new {@link Abs}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Abs}. */ public static Abs absoluteValueOf(AggregationExpression expression) { @@ -581,7 +581,7 @@ public static Abs absoluteValueOf(AggregationExpression expression) { * Creates new {@link Abs}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Abs}. */ public static Abs absoluteValueOf(Number value) { @@ -610,7 +610,7 @@ protected String getMongoMethod() { * Creates new {@link Add}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Add}. */ public static Add valueOf(String fieldReference) { @@ -622,7 +622,7 @@ public static Add valueOf(String fieldReference) { * Creates new {@link Add}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Add}. */ public static Add valueOf(AggregationExpression expression) { @@ -634,7 +634,7 @@ public static Add valueOf(AggregationExpression expression) { * Creates new {@link Add}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Add}. */ public static Add valueOf(Number value) { @@ -642,18 +642,36 @@ public static Add valueOf(Number value) { return new Add(Collections.singletonList(value)); } + /** + * Add the value stored at the given field. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Add}. + */ public Add add(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Add(append(Fields.field(fieldReference))); } + /** + * Add the evaluation result of the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Add}. + */ public Add add(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Add(append(expression)); } + /** + * Add the given value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Add}. + */ public Add add(Number value) { return new Add(append(value)); } @@ -679,7 +697,7 @@ protected String getMongoMethod() { * Creates new {@link Ceil}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Ceil}. */ public static Ceil ceilValueOf(String fieldReference) { @@ -691,7 +709,7 @@ public static Ceil ceilValueOf(String fieldReference) { * Creates new {@link Ceil}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Ceil}. */ public static Ceil ceilValueOf(AggregationExpression expression) { @@ -703,7 +721,7 @@ public static Ceil ceilValueOf(AggregationExpression expression) { * Creates new {@link Ceil}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Ceil}. */ public static Ceil ceilValueOf(Number value) { @@ -732,7 +750,7 @@ protected String getMongoMethod() { * Creates new {@link Divide}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Divide}. */ public static Divide valueOf(String fieldReference) { @@ -744,7 +762,7 @@ public static Divide valueOf(String fieldReference) { * Creates new {@link Divide}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Divide}. */ public static Divide valueOf(AggregationExpression expression) { @@ -756,7 +774,7 @@ public static Divide valueOf(AggregationExpression expression) { * Creates new {@link Divide}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Divide}. */ public static Divide valueOf(Number value) { @@ -764,18 +782,36 @@ public static Divide valueOf(Number value) { return new Divide(Collections.singletonList(value)); } + /** + * Divide by the value stored at the given field. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Divide}. + */ public Divide divideBy(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Divide(append(Fields.field(fieldReference))); } + /** + * Divide by the evaluation results of the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Divide}. + */ public Divide divideBy(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Divide(append(expression)); } + /** + * Divide by the given value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Divide}. + */ public Divide divideBy(Number value) { return new Divide(append(value)); } @@ -801,7 +837,7 @@ protected String getMongoMethod() { * Creates new {@link Exp}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Exp}. */ public static Exp expValueOf(String fieldReference) { @@ -813,7 +849,7 @@ public static Exp expValueOf(String fieldReference) { * Creates new {@link Exp}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Exp}. */ public static Exp expValueOf(AggregationExpression expression) { @@ -825,7 +861,7 @@ public static Exp expValueOf(AggregationExpression expression) { * Creates new {@link Exp}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Exp}. */ public static Exp expValueOf(Number value) { @@ -854,7 +890,7 @@ protected String getMongoMethod() { * Creates new {@link Floor}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Floor}. */ public static Floor floorValueOf(String fieldReference) { @@ -866,7 +902,7 @@ public static Floor floorValueOf(String fieldReference) { * Creates new {@link Floor}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Floor}. */ public static Floor floorValueOf(AggregationExpression expression) { @@ -878,7 +914,7 @@ public static Floor floorValueOf(AggregationExpression expression) { * Creates new {@link Floor}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Floor}. */ public static Floor floorValueOf(Number value) { @@ -907,7 +943,7 @@ protected String getMongoMethod() { * Creates new {@link Ln}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Ln}. */ public static Ln lnValueOf(String fieldReference) { @@ -919,7 +955,7 @@ public static Ln lnValueOf(String fieldReference) { * Creates new {@link Ln}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Ln}. */ public static Ln lnValueOf(AggregationExpression expression) { @@ -931,7 +967,7 @@ public static Ln lnValueOf(AggregationExpression expression) { * Creates new {@link Ln}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Ln}. */ public static Ln lnValueOf(Number value) { @@ -960,7 +996,7 @@ protected String getMongoMethod() { * Creates new {@link Min}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Log}. */ public static Log valueOf(String fieldReference) { @@ -972,7 +1008,7 @@ public static Log valueOf(String fieldReference) { * Creates new {@link Log}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Log}. */ public static Log valueOf(AggregationExpression expression) { @@ -992,18 +1028,36 @@ public static Log valueOf(Number value) { return new Log(Collections.singletonList(value)); } + /** + * Use the value stored at the given field as log base. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Log}. + */ public Log log(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Log(append(Fields.field(fieldReference))); } + /** + * Use the evaluated value of the given {@link AggregationExpression} as log base. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Log}. + */ public Log log(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Log(append(expression)); } + /** + * Use the given value as log base. + * + * @param base must not be {@literal null}. + * @return new instance of {@link Log}. + */ public Log log(Number base) { return new Log(append(base)); } @@ -1029,7 +1083,7 @@ protected String getMongoMethod() { * Creates new {@link Log10}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Log10}. */ public static Log10 log10ValueOf(String fieldReference) { @@ -1041,7 +1095,7 @@ public static Log10 log10ValueOf(String fieldReference) { * Creates new {@link Log10}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Log10}. */ public static Log10 log10ValueOf(AggregationExpression expression) { @@ -1053,7 +1107,7 @@ public static Log10 log10ValueOf(AggregationExpression expression) { * Creates new {@link Log10}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Log10}. */ public static Log10 log10ValueOf(Number value) { @@ -1082,7 +1136,7 @@ protected String getMongoMethod() { * Creates new {@link Mod}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Mod}. */ public static Mod valueOf(String fieldReference) { @@ -1094,7 +1148,7 @@ public static Mod valueOf(String fieldReference) { * Creates new {@link Mod}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Mod}. */ public static Mod valueOf(AggregationExpression expression) { @@ -1106,7 +1160,7 @@ public static Mod valueOf(AggregationExpression expression) { * Creates new {@link Mod}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Mod}. */ public static Mod valueOf(Number value) { @@ -1114,18 +1168,36 @@ public static Mod valueOf(Number value) { return new Mod(Collections.singletonList(value)); } + /** + * Use the value stored at the given field as mod base. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Mod}. + */ public Mod mod(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Mod(append(Fields.field(fieldReference))); } + /** + * Use evaluated value of the given {@link AggregationExpression} as mod base. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Mod}. + */ public Mod mod(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Mod(append(expression)); } + /** + * Use the given value as mod base. + * + * @param base must not be {@literal null}. + * @return new instance of {@link Mod}. + */ public Mod mod(Number base) { return new Mod(append(base)); } @@ -1151,7 +1223,7 @@ protected String getMongoMethod() { * Creates new {@link Multiply}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Multiply}. */ public static Multiply valueOf(String fieldReference) { @@ -1163,7 +1235,7 @@ public static Multiply valueOf(String fieldReference) { * Creates new {@link Multiply}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Multiply}. */ public static Multiply valueOf(AggregationExpression expression) { @@ -1175,7 +1247,7 @@ public static Multiply valueOf(AggregationExpression expression) { * Creates new {@link Multiply}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Multiply}. */ public static Multiply valueOf(Number value) { @@ -1183,18 +1255,36 @@ public static Multiply valueOf(Number value) { return new Multiply(Collections.singletonList(value)); } + /** + * Multiply by the value stored at the given field. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Multiply}. + */ public Multiply multiplyBy(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Multiply(append(Fields.field(fieldReference))); } + /** + * Multiply by the evaluated value of the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Multiply}. + */ public Multiply multiplyBy(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Multiply(append(expression)); } + /** + * Multiply by the given value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Multiply}. + */ public Multiply multiplyBy(Number value) { return new Multiply(append(value)); } @@ -1252,18 +1342,36 @@ public static Pow valueOf(Number value) { return new Pow(Collections.singletonList(value)); } + /** + * Pow by the value stored at the given field. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Pow}. + */ public Pow pow(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Pow(append(Fields.field(fieldReference))); } + /** + * Pow by the evaluated value of the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Pow}. + */ public Pow pow(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Pow(append(expression)); } + /** + * Pow by the given value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Pow}. + */ public Pow pow(Number value) { return new Pow(append(value)); } @@ -1289,7 +1397,7 @@ protected String getMongoMethod() { * Creates new {@link Sqrt}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Sqrt}. */ public static Sqrt sqrtOf(String fieldReference) { @@ -1301,7 +1409,7 @@ public static Sqrt sqrtOf(String fieldReference) { * Creates new {@link Sqrt}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Sqrt}. */ public static Sqrt sqrtOf(AggregationExpression expression) { @@ -1313,7 +1421,7 @@ public static Sqrt sqrtOf(AggregationExpression expression) { * Creates new {@link Sqrt}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Sqrt}. */ public static Sqrt sqrtOf(Number value) { @@ -1342,7 +1450,7 @@ protected String getMongoMethod() { * Creates new {@link Subtract}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Subtract}. */ public static Subtract valueOf(String fieldReference) { @@ -1354,7 +1462,7 @@ public static Subtract valueOf(String fieldReference) { * Creates new {@link Subtract}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Subtract}. */ public static Subtract valueOf(AggregationExpression expression) { @@ -1366,7 +1474,7 @@ public static Subtract valueOf(AggregationExpression expression) { * Creates new {@link Subtract}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Subtract}. */ public static Subtract valueOf(Number value) { @@ -1374,18 +1482,36 @@ public static Subtract valueOf(Number value) { return new Subtract(Collections.singletonList(value)); } + /** + * Subtract the value stored at the given field. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Pow}. + */ public Subtract subtract(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Subtract(append(Fields.field(fieldReference))); } + /** + * Subtract the evaluated value of the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Pow}. + */ public Subtract subtract(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Subtract(append(expression)); } + /** + * Subtract the given value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Pow}. + */ public Subtract subtract(Number value) { return new Subtract(append(value)); } @@ -1411,7 +1537,7 @@ protected String getMongoMethod() { * Creates new {@link Trunc}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Trunc}. */ public static Trunc truncValueOf(String fieldReference) { @@ -1423,7 +1549,7 @@ public static Trunc truncValueOf(String fieldReference) { * Creates new {@link Trunc}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Trunc}. */ public static Trunc truncValueOf(AggregationExpression expression) { @@ -1435,7 +1561,7 @@ public static Trunc truncValueOf(AggregationExpression expression) { * Creates new {@link Trunc}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Trunc}. */ public static Trunc truncValueOf(Number value) { @@ -1502,7 +1628,7 @@ public static Round round(Number value) { /** * The place to round to. Can be between -20 and 100, exclusive. * - * @param place + * @param place value between -20 and 100, exclusive. * @return new instance of {@link Round}. */ public Round place(int place) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java index ee1b3806b3..5a982c06f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java @@ -43,7 +43,7 @@ public class ArrayOperators { * Take the array referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ArrayOperatorFactory}. */ public static ArrayOperatorFactory arrayOf(String fieldReference) { return new ArrayOperatorFactory(fieldReference); @@ -53,7 +53,7 @@ public static ArrayOperatorFactory arrayOf(String fieldReference) { * Take the array referenced resulting from the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ArrayOperatorFactory}. */ public static ArrayOperatorFactory arrayOf(AggregationExpression expression) { return new ArrayOperatorFactory(expression); @@ -123,8 +123,8 @@ public ArrayOperatorFactory(Collection values) { * Creates new {@link AggregationExpression} that takes the associated array and returns the element at the * specified array {@literal position}. * - * @param position - * @return + * @param position the element index. + * @return new instance of {@link ArrayElemAt}. */ public ArrayElemAt elementAt(int position) { return createArrayElemAt().elementAt(position); @@ -135,7 +135,7 @@ public ArrayElemAt elementAt(int position) { * resulting form the given {@literal expression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ArrayElemAt}. */ public ArrayElemAt elementAt(AggregationExpression expression) { @@ -148,7 +148,7 @@ public ArrayElemAt elementAt(AggregationExpression expression) { * defined by the referenced {@literal field}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ArrayElemAt}. */ public ArrayElemAt elementAt(String fieldReference) { @@ -170,7 +170,7 @@ private ArrayElemAt createArrayElemAt() { * {@literal arrayFieldReference} to it. * * @param arrayFieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ConcatArrays}. */ public ConcatArrays concat(String arrayFieldReference) { @@ -183,7 +183,7 @@ public ConcatArrays concat(String arrayFieldReference) { * the given {@literal expression} to it. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ConcatArrays}. */ public ConcatArrays concat(AggregationExpression expression) { @@ -204,7 +204,7 @@ private ConcatArrays createConcatArrays() { * Creates new {@link AggregationExpression} that takes the associated array and selects a subset of the array to * return based on the specified condition. * - * @return + * @return new instance of {@link AsBuilder} to create a {@link Filter}. */ public AsBuilder filter() { @@ -219,7 +219,7 @@ public AsBuilder filter() { /** * Creates new {@link AggregationExpression} that takes the associated array and an check if its an array. * - * @return + * @return new instance of {@link IsArray}. */ public IsArray isArray() { @@ -231,7 +231,7 @@ public IsArray isArray() { /** * Creates new {@link AggregationExpression} that takes the associated array and retrieves its length. * - * @return + * @return new instance of {@link Size}. */ public Size length() { @@ -245,7 +245,7 @@ public Size length() { /** * Creates new {@link AggregationExpression} that takes the associated array and selects a subset from it. * - * @return + * @return new instance of {@link Slice}. */ public Slice slice() { @@ -261,7 +261,7 @@ public Slice slice() { * value and returns the array index (zero-based) of the first occurrence. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfArray}. */ public IndexOfArray indexOf(Object value) { @@ -276,7 +276,7 @@ public IndexOfArray indexOf(Object value) { /** * Creates new {@link AggregationExpression} that returns an array with the elements in reverse order. * - * @return + * @return new instance of {@link ReverseArray}. */ public ReverseArray reverse() { @@ -293,7 +293,7 @@ public ReverseArray reverse() { * an array and combines them into a single value. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ReduceInitialValueBuilder} to create {@link Reduce}. */ public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(AggregationExpression expression) { @@ -305,8 +305,8 @@ public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(AggregationExpressi * Start creating new {@link AggregationExpression} that applies an {@link AggregationExpression} to each element in * an array and combines them into a single value. * - * @param expressions - * @return + * @param expressions must not be {@literal null}. + * @return new instance of {@link ReduceInitialValueBuilder} to create {@link Reduce}. */ public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(PropertyExpression... expressions) { @@ -320,7 +320,7 @@ public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(PropertyExpression. * the second input array, etc. * * @param arrays must not be {@literal null}. - * @return + * @return new instance of {@link Zip}. */ public Zip zipWith(Object... arrays) { @@ -336,7 +336,7 @@ public Zip zipWith(Object... arrays) { * associated array. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link In}. */ public In containsValue(Object value) { @@ -413,7 +413,7 @@ protected String getMongoMethod() { * Creates new {@link ArrayElemAt}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ArrayElemAt}. */ public static ArrayElemAt arrayOf(String fieldReference) { @@ -425,7 +425,7 @@ public static ArrayElemAt arrayOf(String fieldReference) { * Creates new {@link ArrayElemAt}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ArrayElemAt}. */ public static ArrayElemAt arrayOf(AggregationExpression expression) { @@ -446,16 +446,34 @@ public static ArrayElemAt arrayOf(Collection values) { return new ArrayElemAt(Collections.singletonList(values)); } + /** + * Use the element with given index number. + * + * @param index the index number + * @return new instance of {@link ArrayElemAt}. + */ public ArrayElemAt elementAt(int index) { return new ArrayElemAt(append(index)); } + /** + * Use the element at the index number evaluated from the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link ArrayElemAt}. + */ public ArrayElemAt elementAt(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new ArrayElemAt(append(expression)); } + /** + * Use the element at the index number traken from the given field. + * + * @param arrayFieldReference the field name. + * @return new instance of {@link ArrayElemAt}. + */ public ArrayElemAt elementAt(String arrayFieldReference) { Assert.notNull(arrayFieldReference, "ArrayReference must not be null!"); @@ -483,7 +501,7 @@ protected String getMongoMethod() { * Creates new {@link ConcatArrays}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ConcatArrays}. */ public static ConcatArrays arrayOf(String fieldReference) { @@ -495,7 +513,7 @@ public static ConcatArrays arrayOf(String fieldReference) { * Creates new {@link ConcatArrays}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ConcatArrays}. */ public static ConcatArrays arrayOf(AggregationExpression expression) { @@ -516,12 +534,24 @@ public static ConcatArrays arrayOf(Collection values) { return new ConcatArrays(Collections.singletonList(values)); } + /** + * Concat with the array stored at the given field. + * + * @param arrayFieldReference must not be {@literal null}. + * @return new instance of {@link ConcatArrays}. + */ public ConcatArrays concat(String arrayFieldReference) { Assert.notNull(arrayFieldReference, "ArrayFieldReference must not be null!"); return new ConcatArrays(append(Fields.field(arrayFieldReference))); } + /** + * Concat with the array resulting from the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link ConcatArrays}. + */ public ConcatArrays concat(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); @@ -574,7 +604,7 @@ public static AsBuilder filter(Field field) { * Set the {@literal values} to apply the {@code $filter} to. * * @param values must not be {@literal null}. - * @return + * @return new instance of {@link AsBuilder} to create the {@link Filter}. */ public static AsBuilder filter(List values) { @@ -651,7 +681,7 @@ public interface AsBuilder { * Set the {@literal variableName} for the elements in the input array. * * @param variableName must not be {@literal null}. - * @return + * @return never {@literal null}. */ ConditionBuilder as(String variableName); } @@ -665,7 +695,7 @@ public interface ConditionBuilder { * Set the {@link AggregationExpression} that determines whether to include the element in the resulting array. * * @param expression must not be {@literal null}. - * @return + * @return never {@literal null}. */ Filter by(AggregationExpression expression); @@ -673,7 +703,7 @@ public interface ConditionBuilder { * Set the {@literal expression} that determines whether to include the element in the resulting array. * * @param expression must not be {@literal null}. - * @return + * @return never {@literal null}. */ Filter by(String expression); @@ -681,7 +711,7 @@ public interface ConditionBuilder { * Set the {@literal expression} that determines whether to include the element in the resulting array. * * @param expression must not be {@literal null}. - * @return + * @return never {@literal null}. */ Filter by(Document expression); } @@ -700,7 +730,7 @@ static final class FilterExpressionBuilder implements InputBuilder, AsBuilder, C /** * Creates new {@link InputBuilder}. * - * @return + * @return new instance of {@link FilterExpressionBuilder}. */ public static InputBuilder newBuilder() { return new FilterExpressionBuilder(); @@ -800,7 +830,7 @@ protected String getMongoMethod() { * Creates new {@link IsArray}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IsArray}. */ public static IsArray isArray(String fieldReference) { @@ -812,7 +842,7 @@ public static IsArray isArray(String fieldReference) { * Creates new {@link IsArray}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IsArray}. */ public static IsArray isArray(AggregationExpression expression) { @@ -841,7 +871,7 @@ protected String getMongoMethod() { * Creates new {@link Size}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Size}. */ public static Size lengthOfArray(String fieldReference) { @@ -853,7 +883,7 @@ public static Size lengthOfArray(String fieldReference) { * Creates new {@link Size}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Size}. */ public static Size lengthOfArray(AggregationExpression expression) { @@ -895,7 +925,7 @@ protected String getMongoMethod() { * Creates new {@link Slice}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Slice}. */ public static Slice sliceArrayOf(String fieldReference) { @@ -907,7 +937,7 @@ public static Slice sliceArrayOf(String fieldReference) { * Creates new {@link Slice}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Slice}. */ public static Slice sliceArrayOf(AggregationExpression expression) { @@ -928,10 +958,22 @@ public static Slice sliceArrayOf(Collection values) { return new Slice(Collections.singletonList(values)); } + /** + * Slice the number of elements. + * + * @param nrElements elements to slice. + * @return new instance of {@link Slice}. + */ public Slice itemCount(int nrElements) { return new Slice(append(nrElements)); } + /** + * Slice using offset and count. + * + * @param position the start position + * @return new instance of {@link SliceElementsBuilder} to create {@link Slice}. + */ public SliceElementsBuilder offset(final int position) { return new SliceElementsBuilder() { @@ -978,7 +1020,7 @@ protected String getMongoMethod() { * Start creating new {@link IndexOfArray}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfArray}. */ public static IndexOfArrayBuilder arrayOf(String fieldReference) { @@ -990,7 +1032,7 @@ public static IndexOfArrayBuilder arrayOf(String fieldReference) { * Start creating new {@link IndexOfArray}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfArray}. */ public static IndexOfArrayBuilder arrayOf(AggregationExpression expression) { @@ -1002,7 +1044,7 @@ public static IndexOfArrayBuilder arrayOf(AggregationExpression expression) { * Start creating new {@link IndexOfArray}. * * @param values must not be {@literal null}. - * @return new instance of {@link IndexOfArray}. + * @return new instance of {@link IndexOfArrayBuilder} to create {@link IndexOfArray}. * @since 2.2 */ public static IndexOfArrayBuilder arrayOf(Collection values) { @@ -1011,6 +1053,12 @@ public static IndexOfArrayBuilder arrayOf(Collection values) { return new IndexOfArrayBuilder(values); } + /** + * Lookup within a given range. + * + * @param range the lookup range. + * @return new instance of {@link IndexOfArray}. + */ public IndexOfArray within(Range range) { return new IndexOfArray(append(AggregationUtils.toRangeValues(range))); } @@ -1030,7 +1078,7 @@ private IndexOfArrayBuilder(Object targetArray) { * Set the {@literal value} to check for its index in the array. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfArray}. */ public IndexOfArray indexOf(Object value) { @@ -1060,7 +1108,7 @@ protected String getMongoMethod() { * Start creating new {@link RangeOperator}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link RangeOperatorBuilder} to create {@link RangeOperator}. */ public static RangeOperatorBuilder rangeStartingAt(String fieldReference) { return new RangeOperatorBuilder(Fields.field(fieldReference)); @@ -1070,7 +1118,7 @@ public static RangeOperatorBuilder rangeStartingAt(String fieldReference) { * Start creating new {@link RangeOperator}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link RangeOperatorBuilder} to create {@link RangeOperator}. */ public static RangeOperatorBuilder rangeStartingAt(AggregationExpression expression) { return new RangeOperatorBuilder(expression); @@ -1080,7 +1128,7 @@ public static RangeOperatorBuilder rangeStartingAt(AggregationExpression express * Start creating new {@link RangeOperator}. * * @param value - * @return + * @return new instance of {@link RangeOperator}. */ public static RangeOperatorBuilder rangeStartingAt(long value) { return new RangeOperatorBuilder(value); @@ -1102,7 +1150,7 @@ private RangeOperatorBuilder(Object startPoint) { * Creates new {@link RangeOperator}. * * @param index - * @return + * @return new instance of {@link RangeOperator}. */ public RangeOperator to(long index) { return new RangeOperator(Arrays.asList(startPoint, index)); @@ -1112,7 +1160,7 @@ public RangeOperator to(long index) { * Creates new {@link RangeOperator}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link RangeOperator}. */ public RangeOperator to(AggregationExpression expression) { return new RangeOperator(Arrays.asList(startPoint, expression)); @@ -1122,7 +1170,7 @@ public RangeOperator to(AggregationExpression expression) { * Creates new {@link RangeOperator}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link RangeOperator}. */ public RangeOperator to(String fieldReference) { return new RangeOperator(Arrays.asList(startPoint, Fields.field(fieldReference))); @@ -1150,7 +1198,7 @@ protected String getMongoMethod() { * Creates new {@link ReverseArray} given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ReverseArray}. */ public static ReverseArray reverseArrayOf(String fieldReference) { return new ReverseArray(Fields.field(fieldReference)); @@ -1160,7 +1208,7 @@ public static ReverseArray reverseArrayOf(String fieldReference) { * Creates new {@link ReverseArray} given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ReverseArray}. */ public static ReverseArray reverseArrayOf(AggregationExpression expression) { return new ReverseArray(expression); @@ -1239,7 +1287,7 @@ private Object getMappedValue(Object value, AggregationOperationContext context) * Start creating new {@link Reduce}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link InitialValueBuilder} to create {@link Reduce}. */ public static InitialValueBuilder arrayOf(final String fieldReference) { @@ -1267,7 +1315,7 @@ public Reduce reduce(PropertyExpression... expressions) { Assert.notNull(expressions, "PropertyExpressions must not be null"); return new Reduce(Fields.field(fieldReference), initialValue, - Arrays. asList(expressions)); + Arrays.asList(expressions)); } }; } @@ -1278,7 +1326,7 @@ public Reduce reduce(PropertyExpression... expressions) { * Start creating new {@link Reduce}. * * @param arrayValueExpression must not be {@literal null}. - * @return + * @return new instance of {@link InitialValueBuilder} to create {@link Reduce}. */ public static InitialValueBuilder arrayOf(final AggregationExpression arrayValueExpression) { @@ -1318,7 +1366,7 @@ public interface InitialValueBuilder { * Define the initial cumulative value set before in is applied to the first element of the input array. * * @param initialValue must not be {@literal null}. - * @return + * @return never {@literal null}. */ ReduceBuilder withInitialValue(Object initialValue); } @@ -1335,7 +1383,7 @@ public interface ReduceBuilder { * {@link Variable#VALUE} are available. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Reduce}. */ Reduce reduce(AggregationExpression expression); @@ -1346,7 +1394,7 @@ public interface ReduceBuilder { * {@link Variable#VALUE} are available. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link Reduce}. */ Reduce reduce(PropertyExpression... expressions); } @@ -1372,7 +1420,7 @@ protected PropertyExpression(String propertyName, AggregationExpression aggregat * Define a result property for an {@link AggregationExpression} used in {@link Reduce}. * * @param name must not be {@literal null}. - * @return + * @return new instance of {@link AsBuilder} to create {@link Reduce}. */ public static AsBuilder property(final String name) { @@ -1402,7 +1450,7 @@ public interface AsBuilder { * Set the {@link AggregationExpression} resulting in the properties value. * * @param expression must not be {@literal null}. - * @return + * @return never {@literal null}. */ PropertyExpression definedAs(AggregationExpression expression); } @@ -1459,7 +1507,7 @@ public String toString() { * eg. {@code $$value.product} * * @param property must not be {@literal null}. - * @return + * @return never {@literal null}. */ public Field referringTo(final String property) { @@ -1508,7 +1556,7 @@ protected String getMongoMethod() { * Start creating new {@link Zip}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ZipBuilder} to create {@link Zip}. */ public static ZipBuilder arrayOf(String fieldReference) { @@ -1520,7 +1568,7 @@ public static ZipBuilder arrayOf(String fieldReference) { * Start creating new {@link Zip}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ZipBuilder} to create {@link Zip}. */ public static ZipBuilder arrayOf(AggregationExpression expression) { @@ -1544,7 +1592,7 @@ public static ZipBuilder arrayOf(Collection values) { /** * Create new {@link Zip} and set the {@code useLongestLength} property to {@literal true}. * - * @return + * @return new instance of {@link Zip}. */ public Zip useLongestLength() { return new Zip(append("useLongestLength", true)); @@ -1554,7 +1602,7 @@ public Zip useLongestLength() { * Optionally provide a default value. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Zip}. */ public Zip defaultTo(String fieldReference) { @@ -1566,7 +1614,7 @@ public Zip defaultTo(String fieldReference) { * Optionally provide a default value. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Zip}. */ public Zip defaultTo(AggregationExpression expression) { @@ -1578,7 +1626,7 @@ public Zip defaultTo(AggregationExpression expression) { * Optionally provide a default value. * * @param array must not be {@literal null}. - * @return + * @return new instance of {@link Zip}. */ public Zip defaultTo(Object[] array) { @@ -1602,7 +1650,7 @@ private ZipBuilder(Object sourceArray) { * array, etc. * * @param arrays arrays to zip the referenced one with. must not be {@literal null}. - * @return + * @return new instance of {@link Zip}. */ public Zip zip(Object... arrays) { @@ -1616,7 +1664,7 @@ public Zip zip(Object... arrays) { } } - return new Zip(Collections. singletonMap("inputs", sourceArrays)); + return new Zip(Collections.singletonMap("inputs", sourceArrays)); } } } @@ -1627,7 +1675,7 @@ public Zip zip(Object... arrays) { * @author Christoph Strobl * @author Shashank Sharma * @see https://docs.mongodb.com/manual/reference/operator/aggregation/in/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/in/">https://docs.mongodb.com/manual/reference/operator/aggregation/in/ * @since 2.2 */ public static class In extends AbstractAggregationExpression { @@ -1645,7 +1693,7 @@ protected String getMongoMethod() { * Start creating {@link In}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link InBuilder} to create {@link In}. */ public static InBuilder arrayOf(String fieldReference) { @@ -1662,7 +1710,7 @@ public static InBuilder arrayOf(String fieldReference) { * Start creating {@link In}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link InBuilder} to create {@link In}. */ public static InBuilder arrayOf(AggregationExpression expression) { @@ -1704,7 +1752,7 @@ public interface InBuilder { * Set the {@literal value} to check for existence in the array. * * @param value must not be {@literal value}. - * @return + * @return new instance of {@link In}. */ In containsValue(Object value); } @@ -1716,7 +1764,7 @@ public interface InBuilder { * * @author Christoph Strobl * @see https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/">https://docs.mongodb.com/manual/reference/operator/aggregation/arrayToObject/ * @since 2.1 */ public static class ArrayToObject extends AbstractAggregationExpression { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java index ff1b0e8e4e..b651a89616 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java @@ -34,7 +34,7 @@ public class BooleanOperators { * Take the array referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link BooleanOperatorFactory}. */ public static BooleanOperatorFactory valueOf(String fieldReference) { return new BooleanOperatorFactory(fieldReference); @@ -44,7 +44,7 @@ public static BooleanOperatorFactory valueOf(String fieldReference) { * Take the value resulting of the given {@link AggregationExpression}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link BooleanOperatorFactory}. */ public static BooleanOperatorFactory valueOf(AggregationExpression fieldReference) { return new BooleanOperatorFactory(fieldReference); @@ -55,7 +55,7 @@ public static BooleanOperatorFactory valueOf(AggregationExpression fieldReferenc * opposite boolean value. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Not}. */ public static Not not(String fieldReference) { return Not.not(fieldReference); @@ -66,7 +66,7 @@ public static Not not(String fieldReference) { * and returns the opposite boolean value. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Not}. */ public static Not not(AggregationExpression expression) { return Not.not(expression); @@ -109,7 +109,7 @@ public BooleanOperatorFactory(AggregationExpression expression) { * all of the expressions are {@literal true}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link And}. */ public And and(AggregationExpression expression) { @@ -122,7 +122,7 @@ public And and(AggregationExpression expression) { * all of the expressions are {@literal true}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link And}. */ public And and(String fieldReference) { @@ -139,7 +139,7 @@ private And createAnd() { * any of the expressions are {@literal true}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Or}. */ public Or or(AggregationExpression expression) { @@ -152,7 +152,7 @@ public Or or(AggregationExpression expression) { * any of the expressions are {@literal true}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Or}. */ public Or or(String fieldReference) { @@ -167,7 +167,7 @@ private Or createOr() { /** * Creates new {@link AggregationExpression} that evaluates a boolean and returns the opposite boolean value. * - * @return + * @return new instance of {@link Not}. */ public Not not() { return usesFieldRef() ? Not.not(fieldReference) : Not.not(expression); @@ -198,8 +198,8 @@ protected String getMongoMethod() { * Creates new {@link And} that evaluates one or more expressions and returns {@literal true} if all of the * expressions are {@literal true}. * - * @param expressions - * @return + * @param expressions must not be {@literal null}. + * @return new instance of {@link And}. */ public static And and(Object... expressions) { return new And(Arrays.asList(expressions)); @@ -209,7 +209,7 @@ public static And and(Object... expressions) { * Creates new {@link And} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link And}. */ public And andExpression(AggregationExpression expression) { @@ -221,7 +221,7 @@ public And andExpression(AggregationExpression expression) { * Creates new {@link And} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link And}. */ public And andField(String fieldReference) { @@ -233,7 +233,7 @@ public And andField(String fieldReference) { * Creates new {@link And} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link And}. */ public And andValue(Object value) { @@ -263,7 +263,7 @@ protected String getMongoMethod() { * expressions are {@literal true}. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link Or}. */ public static Or or(Object... expressions) { @@ -275,7 +275,7 @@ public static Or or(Object... expressions) { * Creates new {@link Or} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Or}. */ public Or orExpression(AggregationExpression expression) { @@ -287,7 +287,7 @@ public Or orExpression(AggregationExpression expression) { * Creates new {@link Or} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Or}. */ public Or orField(String fieldReference) { @@ -299,7 +299,7 @@ public Or orField(String fieldReference) { * Creates new {@link Or} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Or}. */ public Or orValue(Object value) { @@ -329,7 +329,7 @@ protected String getMongoMethod() { * value. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Not}. */ public static Not not(String fieldReference) { @@ -342,7 +342,7 @@ public static Not not(String fieldReference) { * returns the opposite boolean value. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Not}. */ public static Not not(AggregationExpression expression) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java index cbab756934..bb7e032efa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java @@ -113,7 +113,7 @@ public Document toDocument(AggregationOperationContext context) { * Configures a number of bucket {@literal buckets} and return a new {@link BucketAutoOperation}. * * @param buckets must be a positive number. - * @return + * @return new instance of {@link BucketAutoOperation}. */ public BucketAutoOperation withBuckets(int buckets) { @@ -128,7 +128,7 @@ public BucketAutoOperation withBuckets(int buckets) { * Use either predefined {@link Granularities} or provide a own one. * * @param granularity must not be {@literal null}. - * @return + * @return new instance of {@link BucketAutoOperation}. */ public BucketAutoOperation withGranularity(Granularity granularity) { @@ -209,7 +209,7 @@ public static class ExpressionBucketAutoOperationBuilder * * @param expression must not be {@literal null}. * @param operation must not be {@literal null}. - * @param parameters + * @param parameters must not be {@literal null}. */ protected ExpressionBucketAutoOperationBuilder(String expression, BucketAutoOperation operation, Object[] parameters) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java index c9ea533fae..9fb67e624b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java @@ -110,7 +110,7 @@ public Document toDocument(AggregationOperationContext context) { * Configures a default bucket {@literal literal} and return a new {@link BucketOperation}. * * @param literal must not be {@literal null}. - * @return + * @return new instance of {@link BucketOperation}. */ public BucketOperation withDefaultBucket(Object literal) { @@ -123,7 +123,7 @@ public BucketOperation withDefaultBucket(Object literal) { * preserved and the new {@literal boundaries} are appended. * * @param boundaries must not be {@literal null}. - * @return + * @return new instance of {@link BucketOperation}. */ public BucketOperation withBoundaries(Object... boundaries) { @@ -209,7 +209,7 @@ public static class ExpressionBucketOperationBuilder * * @param expression must not be {@literal null}. * @param operation must not be {@literal null}. - * @param parameters + * @param parameters must not be {@literal null}. */ protected ExpressionBucketOperationBuilder(String expression, BucketOperation operation, Object[] parameters) { super(expression, operation, parameters); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java index 75c9e9a553..feee4422e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java @@ -21,14 +21,13 @@ import java.util.Collections; import java.util.List; +import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.OutputBuilder; import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder; import org.springframework.expression.spel.ast.Projection; import org.springframework.util.Assert; -import org.bson.Document; - /** * Base class for bucket operations that support output expressions the aggregation framework.
      * Bucket stages collect documents into buckets and can contribute output fields.
      @@ -104,7 +103,7 @@ protected BucketOperationSupport(BucketOperationSupport operationSupport, * * @param expression the SpEL expression, must not be {@literal null} or empty. * @param params must not be {@literal null} - * @return + * @return new instance of {@link ExpressionBucketOperationBuilderSupport} to create {@link BucketOperation}. */ public abstract ExpressionBucketOperationBuilderSupport andOutputExpression(String expression, Object... params); @@ -114,7 +113,7 @@ public abstract ExpressionBucketOperationBuilderSupport andOutputExpressio * resulting bucket documents. * * @param expression the SpEL expression, must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ public abstract B andOutput(AggregationExpression expression); @@ -124,14 +123,14 @@ public abstract ExpressionBucketOperationBuilderSupport andOutputExpressio * {@literal fieldName}. * * @param fieldName must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ public abstract B andOutput(String fieldName); /** * Creates a new {@link BucketOperationSupport} given to add a count field to the resulting bucket documents. * - * @return + * @return never {@literal null}. */ public B andOutputCount() { return andOutput(new AggregationExpression() { @@ -231,7 +230,7 @@ protected OutputBuilder(Object value, T operation) { * Generates a builder for a {@code $sum}-expression.
      * Count expressions are emulated via {@code $sum: 1}. * - * @return + * @return never {@literal null}. */ public B count() { return sum(1); @@ -240,7 +239,7 @@ public B count() { /** * Generates a builder for a {@code $sum}-expression for the current value. * - * @return + * @return never {@literal null}. */ public B sum() { return apply(Accumulators.SUM); @@ -249,8 +248,8 @@ public B sum() { /** * Generates a builder for a {@code $sum}-expression for the given {@literal value}. * - * @param value - * @return + * @param value must not be {@literal null}. + * @return never {@literal null}. */ public B sum(Number value) { return apply(new OperationOutput(Accumulators.SUM.getMongoOperator(), Collections.singleton(value))); @@ -259,7 +258,7 @@ public B sum(Number value) { /** * Generates a builder for an {@code $last}-expression for the current value.. * - * @return + * @return never {@literal null}. */ public B last() { return apply(Accumulators.LAST); @@ -268,7 +267,7 @@ public B last() { /** * Generates a builder for a {@code $first}-expression the current value. * - * @return + * @return never {@literal null}. */ public B first() { return apply(Accumulators.FIRST); @@ -277,8 +276,7 @@ public B first() { /** * Generates a builder for an {@code $avg}-expression for the current value. * - * @param reference - * @return + * @return never {@literal null}. */ public B avg() { return apply(Accumulators.AVG); @@ -287,7 +285,7 @@ public B avg() { /** * Generates a builder for an {@code $min}-expression for the current value. * - * @return + * @return never {@literal null}. */ public B min() { return apply(Accumulators.MIN); @@ -296,7 +294,7 @@ public B min() { /** * Generates a builder for an {@code $max}-expression for the current value. * - * @return + * @return never {@literal null}. */ public B max() { return apply(Accumulators.MAX); @@ -305,7 +303,7 @@ public B max() { /** * Generates a builder for an {@code $push}-expression for the current value. * - * @return + * @return never {@literal null}. */ public B push() { return apply(Accumulators.PUSH); @@ -314,7 +312,7 @@ public B push() { /** * Generates a builder for an {@code $addToSet}-expression for the current value. * - * @return + * @return never {@literal null}. */ public B addToSet() { return apply(Accumulators.ADDTOSET); @@ -325,7 +323,7 @@ public B addToSet() { * * @param operation the operation name, must not be {@literal null} or empty. * @param values must not be {@literal null}. - * @return + * @return never {@literal null}. */ public B apply(String operation, Object... values) { @@ -342,7 +340,7 @@ public B apply(String operation, Object... values) { * Apply an {@link OperationOutput} to this output. * * @param operationOutput must not be {@literal null}. - * @return + * @return never {@literal null}. */ protected abstract B apply(OperationOutput operationOutput); @@ -354,7 +352,7 @@ private B apply(Accumulators operation) { * Returns the finally to be applied {@link BucketOperation} with the given alias. * * @param alias will never be {@literal null} or empty. - * @return + * @return never {@literal null}. */ public T as(String alias) { @@ -550,8 +548,7 @@ private OperationOutput(Field field, OperationOutput operationOutput) { public Document toDocument(AggregationOperationContext context) { List operationArguments = getOperationArguments(context); - return new Document(operation, - operationArguments.size() == 1 ? operationArguments.get(0) : operationArguments); + return new Document(operation, operationArguments.size() == 1 ? operationArguments.get(0) : operationArguments); } protected List getOperationArguments(AggregationOperationContext context) { @@ -579,7 +576,7 @@ protected List getOperationArguments(AggregationOperationContext context /** * Returns the field that holds the {@link ProjectionOperationBuilder.OperationProjection}. * - * @return + * @return never {@literal null}. */ protected Field getField() { return getExposedField(); @@ -589,7 +586,7 @@ protected Field getField() { * Creates a new instance of this {@link OperationOutput} with the given alias. * * @param alias the alias to set - * @return + * @return new instance of {@link OperationOutput}. */ public OperationOutput withAlias(String alias) { @@ -658,8 +655,8 @@ private static class AggregationExpressionOutput extends Output { /** * Creates a new {@link AggregationExpressionOutput}. * - * @param field - * @param expression + * @param field must not be {@literal null}. + * @param expression must not be {@literal null}. */ protected AggregationExpressionOutput(Field field, AggregationExpression expression) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java index 2ce153a0f8..70bda575e7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java @@ -32,7 +32,7 @@ public class ComparisonOperators { * Take the field referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ComparisonOperatorFactory}. */ public static ComparisonOperatorFactory valueOf(String fieldReference) { return new ComparisonOperatorFactory(fieldReference); @@ -42,7 +42,7 @@ public static ComparisonOperatorFactory valueOf(String fieldReference) { * Take the value resulting from the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ComparisonOperatorFactory}. */ public static ComparisonOperatorFactory valueOf(AggregationExpression expression) { return new ComparisonOperatorFactory(expression); @@ -81,7 +81,7 @@ public ComparisonOperatorFactory(AggregationExpression expression) { * Creates new {@link AggregationExpression} that compares two values. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public Cmp compareTo(String fieldReference) { return createCmp().compareTo(fieldReference); @@ -91,7 +91,7 @@ public Cmp compareTo(String fieldReference) { * Creates new {@link AggregationExpression} that compares two values. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public Cmp compareTo(AggregationExpression expression) { return createCmp().compareTo(expression); @@ -101,7 +101,7 @@ public Cmp compareTo(AggregationExpression expression) { * Creates new {@link AggregationExpression} that compares two values. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public Cmp compareToValue(Object value) { return createCmp().compareToValue(value); @@ -116,7 +116,7 @@ private Cmp createCmp() { * value is equal to the value of the referenced field. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public Eq equalTo(String fieldReference) { return createEq().equalTo(fieldReference); @@ -127,7 +127,7 @@ public Eq equalTo(String fieldReference) { * value is equal to the expression result. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public Eq equalTo(AggregationExpression expression) { return createEq().equalTo(expression); @@ -138,7 +138,7 @@ public Eq equalTo(AggregationExpression expression) { * value is equal to the given value. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public Eq equalToValue(Object value) { return createEq().equalToValue(value); @@ -153,7 +153,7 @@ private Eq createEq() { * value is greater than the value of the referenced field. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public Gt greaterThan(String fieldReference) { return createGt().greaterThan(fieldReference); @@ -164,7 +164,7 @@ public Gt greaterThan(String fieldReference) { * value is greater than the expression result. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public Gt greaterThan(AggregationExpression expression) { return createGt().greaterThan(expression); @@ -175,7 +175,7 @@ public Gt greaterThan(AggregationExpression expression) { * value is greater than the given value. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public Gt greaterThanValue(Object value) { return createGt().greaterThanValue(value); @@ -190,7 +190,7 @@ private Gt createGt() { * value is greater than or equivalent to the value of the referenced field. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public Gte greaterThanEqualTo(String fieldReference) { return createGte().greaterThanEqualTo(fieldReference); @@ -201,7 +201,7 @@ public Gte greaterThanEqualTo(String fieldReference) { * value is greater than or equivalent to the expression result. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public Gte greaterThanEqualTo(AggregationExpression expression) { return createGte().greaterThanEqualTo(expression); @@ -212,7 +212,7 @@ public Gte greaterThanEqualTo(AggregationExpression expression) { * value is greater than or equivalent to the given value. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public Gte greaterThanEqualToValue(Object value) { return createGte().greaterThanEqualToValue(value); @@ -227,7 +227,7 @@ private Gte createGte() { * value is less than the value of the referenced field. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public Lt lessThan(String fieldReference) { return createLt().lessThan(fieldReference); @@ -238,7 +238,7 @@ public Lt lessThan(String fieldReference) { * value is less than the expression result. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public Lt lessThan(AggregationExpression expression) { return createLt().lessThan(expression); @@ -249,7 +249,7 @@ public Lt lessThan(AggregationExpression expression) { * value is less than to the given value. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public Lt lessThanValue(Object value) { return createLt().lessThanValue(value); @@ -264,7 +264,7 @@ private Lt createLt() { * value is less than or equivalent to the value of the referenced field. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public Lte lessThanEqualTo(String fieldReference) { return createLte().lessThanEqualTo(fieldReference); @@ -275,7 +275,7 @@ public Lte lessThanEqualTo(String fieldReference) { * value is less than or equivalent to the expression result. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public Lte lessThanEqualTo(AggregationExpression expression) { return createLte().lessThanEqualTo(expression); @@ -285,8 +285,8 @@ public Lte lessThanEqualTo(AggregationExpression expression) { * Creates new {@link AggregationExpression} that compares two values and returns {@literal true} when the first * value is less than or equivalent to the given value. * - * @param value - * @return + * @param value must not be {@literal null}. + * @return new instance of {@link Lte}. */ public Lte lessThanEqualToValue(Object value) { return createLte().lessThanEqualToValue(value); @@ -301,7 +301,7 @@ private Lte createLte() { * are not equivalent. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public Ne notEqualTo(String fieldReference) { return createNe().notEqualTo(fieldReference); @@ -312,7 +312,7 @@ public Ne notEqualTo(String fieldReference) { * are not equivalent. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public Ne notEqualTo(AggregationExpression expression) { return createNe().notEqualTo(expression); @@ -323,7 +323,7 @@ public Ne notEqualTo(AggregationExpression expression) { * are not equivalent. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public Ne notEqualToValue(Object value) { return createNe().notEqualToValue(value); @@ -358,7 +358,7 @@ protected String getMongoMethod() { * Creates new {@link Cmp}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public static Cmp valueOf(String fieldReference) { @@ -370,7 +370,7 @@ public static Cmp valueOf(String fieldReference) { * Creates new {@link Cmp}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public static Cmp valueOf(AggregationExpression expression) { @@ -382,7 +382,7 @@ public static Cmp valueOf(AggregationExpression expression) { * Creates new {@link Cmp} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public Cmp compareTo(String fieldReference) { @@ -394,7 +394,7 @@ public Cmp compareTo(String fieldReference) { * Creates new {@link Cmp} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public Cmp compareTo(AggregationExpression expression) { @@ -406,7 +406,7 @@ public Cmp compareTo(AggregationExpression expression) { * Creates new {@link Cmp} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Cmp}. */ public Cmp compareToValue(Object value) { @@ -435,7 +435,7 @@ protected String getMongoMethod() { * Creates new {@link Eq}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public static Eq valueOf(String fieldReference) { @@ -447,7 +447,7 @@ public static Eq valueOf(String fieldReference) { * Creates new {@link Eq}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public static Eq valueOf(AggregationExpression expression) { @@ -459,7 +459,7 @@ public static Eq valueOf(AggregationExpression expression) { * Creates new {@link Eq} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public Eq equalTo(String fieldReference) { @@ -471,7 +471,7 @@ public Eq equalTo(String fieldReference) { * Creates new {@link Eq} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public Eq equalTo(AggregationExpression expression) { @@ -483,7 +483,7 @@ public Eq equalTo(AggregationExpression expression) { * Creates new {@link Eq} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Eq}. */ public Eq equalToValue(Object value) { @@ -512,7 +512,7 @@ protected String getMongoMethod() { * Creates new {@link Gt}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public static Gt valueOf(String fieldReference) { @@ -524,7 +524,7 @@ public static Gt valueOf(String fieldReference) { * Creates new {@link Gt}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public static Gt valueOf(AggregationExpression expression) { @@ -536,7 +536,7 @@ public static Gt valueOf(AggregationExpression expression) { * Creates new {@link Gt} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public Gt greaterThan(String fieldReference) { @@ -548,7 +548,7 @@ public Gt greaterThan(String fieldReference) { * Creates new {@link Gt} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public Gt greaterThan(AggregationExpression expression) { @@ -560,7 +560,7 @@ public Gt greaterThan(AggregationExpression expression) { * Creates new {@link Gt} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Gt}. */ public Gt greaterThanValue(Object value) { @@ -589,7 +589,7 @@ protected String getMongoMethod() { * Creates new {@link Lt}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public static Lt valueOf(String fieldReference) { @@ -601,7 +601,7 @@ public static Lt valueOf(String fieldReference) { * Creates new {@link Lt}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public static Lt valueOf(AggregationExpression expression) { @@ -613,7 +613,7 @@ public static Lt valueOf(AggregationExpression expression) { * Creates new {@link Lt} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public Lt lessThan(String fieldReference) { @@ -625,7 +625,7 @@ public Lt lessThan(String fieldReference) { * Creates new {@link Lt} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public Lt lessThan(AggregationExpression expression) { @@ -637,7 +637,7 @@ public Lt lessThan(AggregationExpression expression) { * Creates new {@link Lt} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Lt}. */ public Lt lessThanValue(Object value) { @@ -666,7 +666,7 @@ protected String getMongoMethod() { * Creates new {@link Gte}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public static Gte valueOf(String fieldReference) { @@ -678,7 +678,7 @@ public static Gte valueOf(String fieldReference) { * Creates new {@link Gte}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public static Gte valueOf(AggregationExpression expression) { @@ -690,7 +690,7 @@ public static Gte valueOf(AggregationExpression expression) { * Creates new {@link Gte} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public Gte greaterThanEqualTo(String fieldReference) { @@ -702,7 +702,7 @@ public Gte greaterThanEqualTo(String fieldReference) { * Creates new {@link Gte} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public Gte greaterThanEqualTo(AggregationExpression expression) { @@ -714,7 +714,7 @@ public Gte greaterThanEqualTo(AggregationExpression expression) { * Creates new {@link Gte} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Gte}. */ public Gte greaterThanEqualToValue(Object value) { @@ -743,7 +743,7 @@ protected String getMongoMethod() { * Creates new {@link Lte}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public static Lte valueOf(String fieldReference) { @@ -755,7 +755,7 @@ public static Lte valueOf(String fieldReference) { * Creates new {@link Lte}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public static Lte valueOf(AggregationExpression expression) { @@ -767,7 +767,7 @@ public static Lte valueOf(AggregationExpression expression) { * Creates new {@link Lte} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public Lte lessThanEqualTo(String fieldReference) { @@ -779,7 +779,7 @@ public Lte lessThanEqualTo(String fieldReference) { * Creates new {@link Lte} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public Lte lessThanEqualTo(AggregationExpression expression) { @@ -791,7 +791,7 @@ public Lte lessThanEqualTo(AggregationExpression expression) { * Creates new {@link Lte} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Lte}. */ public Lte lessThanEqualToValue(Object value) { @@ -820,7 +820,7 @@ protected String getMongoMethod() { * Creates new {@link Ne}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public static Ne valueOf(String fieldReference) { @@ -832,7 +832,7 @@ public static Ne valueOf(String fieldReference) { * Creates new {@link Ne}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public static Ne valueOf(AggregationExpression expression) { @@ -844,7 +844,7 @@ public static Ne valueOf(AggregationExpression expression) { * Creates new {@link Ne} with all previously added arguments appending the given one. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public Ne notEqualTo(String fieldReference) { @@ -856,7 +856,7 @@ public Ne notEqualTo(String fieldReference) { * Creates new {@link Ne} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public Ne notEqualTo(AggregationExpression expression) { @@ -868,7 +868,7 @@ public Ne notEqualTo(AggregationExpression expression) { * Creates new {@link Eq} with all previously added arguments appending the given one. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Ne}. */ public Ne notEqualToValue(Object value) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java index 16b8efe79c..5c9d1f3b92 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java @@ -43,7 +43,7 @@ public class ConditionalOperators { * Take the field referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link ConditionalOperatorFactory}. */ public static ConditionalOperatorFactory when(String fieldReference) { return new ConditionalOperatorFactory(fieldReference); @@ -53,7 +53,7 @@ public static ConditionalOperatorFactory when(String fieldReference) { * Take the value resulting from the given {@literal expression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link ConditionalOperatorFactory}. */ public static ConditionalOperatorFactory when(AggregationExpression expression) { return new ConditionalOperatorFactory(expression); @@ -63,7 +63,7 @@ public static ConditionalOperatorFactory when(AggregationExpression expression) * Take the value resulting from the given {@literal criteriaDefinition}. * * @param criteriaDefinition must not be {@literal null}. - * @return + * @return new instance of {@link ConditionalOperatorFactory}. */ public static ConditionalOperatorFactory when(CriteriaDefinition criteriaDefinition) { return new ConditionalOperatorFactory(criteriaDefinition); @@ -75,7 +75,7 @@ public static ConditionalOperatorFactory when(CriteriaDefinition criteriaDefinit * instances of undefined values or missing fields, returns the value of the replacement expression. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IfNull.ThenBuilder} to create {@link IfNull}. */ public static IfNull.ThenBuilder ifNull(String fieldReference) { @@ -89,7 +89,7 @@ public static IfNull.ThenBuilder ifNull(String fieldReference) { * instances of undefined values or missing fields, returns the value of the replacement expression. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IfNull.ThenBuilder} to create {@link IfNull}. */ public static IfNull.ThenBuilder ifNull(AggregationExpression expression) { @@ -103,7 +103,7 @@ public static IfNull.ThenBuilder ifNull(AggregationExpression expression) { * out of the control flow. * * @param conditions must not be {@literal null}. - * @return + * @return new instance of {@link Switch}. */ public static Switch switchCases(CaseOperator... conditions) { return Switch.switchCases(conditions); @@ -115,7 +115,7 @@ public static Switch switchCases(CaseOperator... conditions) { * out of the control flow. * * @param conditions must not be {@literal null}. - * @return + * @return new instance of {@link Switch}. */ public static Switch switchCases(List conditions) { return Switch.switchCases(conditions); @@ -176,7 +176,7 @@ public ConditionalOperatorFactory(CriteriaDefinition criteriaDefinition) { * return expressions. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link OtherwiseBuilder} to create {@link Cond}. */ public OtherwiseBuilder then(Object value) { @@ -189,7 +189,7 @@ public OtherwiseBuilder then(Object value) { * return expressions. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link OtherwiseBuilder} to create {@link Cond}. */ public OtherwiseBuilder thenValueOf(AggregationExpression expression) { @@ -202,7 +202,7 @@ public OtherwiseBuilder thenValueOf(AggregationExpression expression) { * return expressions. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link OtherwiseBuilder} to create {@link Cond}. */ public OtherwiseBuilder thenValueOf(String fieldReference) { @@ -233,9 +233,9 @@ private boolean usesCriteriaDefinition() { * field references}, {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be * converted to a simple MongoDB type. * - * @see https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/ * @author Mark Paluch + * @see https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/ */ public static class IfNull implements AggregationExpression { @@ -251,9 +251,8 @@ private IfNull(Object condition, Object value) { /** * Creates new {@link IfNull}. * - * @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null} - * . - * @return + * @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null}. + * @return never {@literal null}. */ public static ThenBuilder ifNull(String fieldReference) { @@ -265,8 +264,8 @@ public static ThenBuilder ifNull(String fieldReference) { * Creates new {@link IfNull}. * * @param expression the expression to check for a {@literal null} value, field reference must not be - * {@literal null}. - * @return + * {@literal null}. + * @return never {@literal null}. */ public static ThenBuilder ifNull(AggregationExpression expression) { @@ -316,14 +315,14 @@ public interface IfNullBuilder { /** * @param fieldReference the field to check for a {@literal null} value, field reference must not be - * {@literal null}. + * {@literal null}. * @return the {@link ThenBuilder} */ ThenBuilder ifNull(String fieldReference); /** * @param expression the expression to check for a {@literal null} value, field name must not be {@literal null} - * or empty. + * or empty. * @return the {@link ThenBuilder} */ ThenBuilder ifNull(AggregationExpression expression); @@ -336,21 +335,21 @@ public interface ThenBuilder { /** * @param value the value to be used if the {@code $ifNull} condition evaluates {@literal true}. Can be a - * {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB - * representation but must not be {@literal null}. - * @return + * {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB + * representation but must not be {@literal null}. + * @return new instance of {@link IfNull}. */ IfNull then(Object value); /** * @param fieldReference the field holding the replacement value, must not be {@literal null}. - * @return + * @return new instance of {@link IfNull}. */ IfNull thenValueOf(String fieldReference); /** * @param expression the expression yielding to the replacement value, must not be {@literal null}. - * @return + * @return new instance of {@link IfNull}. */ IfNull thenValueOf(AggregationExpression expression); } @@ -364,7 +363,8 @@ static final class IfNullOperatorBuilder implements IfNullBuilder, ThenBuilder { private @Nullable Object condition; - private IfNullOperatorBuilder() {} + private IfNullOperatorBuilder() { + } /** * Creates a new builder for {@link IfNull}. @@ -458,9 +458,15 @@ public static Switch switchCases(CaseOperator... conditions) { public static Switch switchCases(List conditions) { Assert.notNull(conditions, "Conditions must not be null!"); - return new Switch(Collections. singletonMap("branches", new ArrayList(conditions))); + return new Switch(Collections.singletonMap("branches", new ArrayList(conditions))); } + /** + * Set the default value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Switch}. + */ public Switch defaultTo(Object value) { return new Switch(append("default", value)); } @@ -522,7 +528,7 @@ public interface ThenBuilder { * Set the then {@literal value}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link CaseOperator}. */ CaseOperator then(Object value); } @@ -536,10 +542,10 @@ public interface ThenBuilder { * {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be converted to a * simple MongoDB type. * - * @see https://docs.mongodb.com/manual/reference/operator/aggregation/cond/ * @author Mark Paluch * @author Christoph Strobl + * @see https://docs.mongodb.com/manual/reference/operator/aggregation/cond/ */ public static class Cond implements AggregationExpression { @@ -664,7 +670,6 @@ private List getClauses(AggregationOperationContext context, String key, } clauses.add(new Document(key, args)); - } else if (predicate instanceof Document) { Document nested = (Document) predicate; @@ -680,7 +685,6 @@ private List getClauses(AggregationOperationContext context, String key, args.add(nested.get(s)); clauses.add(new Document(s, args)); } - } else if (!isKeyword(key)) { List args = new ArrayList(); @@ -802,8 +806,8 @@ public interface ThenBuilder { /** * @param value the value to be used if the condition evaluates {@literal true}. Can be a {@link Document}, a - * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but - * must not be {@literal null}. + * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but + * must not be {@literal null}. * @return the {@link OtherwiseBuilder} */ OtherwiseBuilder then(Object value); @@ -828,8 +832,8 @@ public interface OtherwiseBuilder { /** * @param value the value to be used if the condition evaluates {@literal false}. Can be a {@link Document}, a - * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but - * must not be {@literal null}. + * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but + * must not be {@literal null}. * @return the {@link Cond} */ Cond otherwise(Object value); @@ -857,7 +861,8 @@ static class ConditionalExpressionBuilder implements WhenBuilder, ThenBuilder, O private @Nullable Object condition; private @Nullable Object thenValue; - private ConditionalExpressionBuilder() {} + private ConditionalExpressionBuilder() { + } /** * Creates a new builder for {@link Cond}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java index ab837f4376..4306e7630a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java @@ -34,9 +34,9 @@ public class CountOperation implements FieldsExposingAggregationOperation { private final String fieldName; /** - * Creates a new {@link CountOperation} given the {@link fieldName} field name. + * Creates a new {@link CountOperation} given the {@literal fieldName} field name. * - * @param asFieldName must not be {@literal null} or empty. + * @param fieldName must not be {@literal null} or empty. */ public CountOperation(String fieldName) { @@ -71,7 +71,7 @@ public static class CountOperationBuilder { * Returns the finally to be applied {@link CountOperation} with the given alias. * * @param fieldName must not be {@literal null} or empty. - * @return + * @return new instance of {@link CountOperation}. */ public CountOperation as(String fieldName) { return new CountOperation(fieldName); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java index 910c658092..9ce1f314fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java @@ -30,7 +30,7 @@ public class DataTypeOperators { * Return the BSON data type of the given {@literal field}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Type}. */ public static Type typeOf(String fieldReference) { return Type.typeOf(fieldReference); @@ -56,7 +56,7 @@ protected String getMongoMethod() { * Creates new {@link Type}. * * @param field must not be {@literal null}. - * @return + * @return new instance of {@link Type}. */ public static Type typeOf(String field) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index b5a8ab0742..6305961c41 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -37,7 +37,7 @@ public class DateOperators { * Take the date referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link DateOperatorFactory}. */ public static DateOperatorFactory dateOf(String fieldReference) { @@ -49,7 +49,7 @@ public static DateOperatorFactory dateOf(String fieldReference) { * Take the date resulting from the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link DateOperatorFactory}. */ public static DateOperatorFactory dateOf(AggregationExpression expression) { @@ -278,7 +278,7 @@ public DateOperatorFactory withTimezone(Timezone timezone) { * Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and * 366. * - * @return + * @return new instance of {@link DayOfYear}. */ public DayOfYear dayOfYear() { return applyTimezone(DayOfYear.dayOfYear(dateReference()), timezone); @@ -288,7 +288,7 @@ public DayOfYear dayOfYear() { * Creates new {@link AggregationExpression} that returns the day of the month for a date as a number between 1 and * 31. * - * @return + * @return new instance of {@link DayOfMonth}. */ public DayOfMonth dayOfMonth() { return applyTimezone(DayOfMonth.dayOfMonth(dateReference()), timezone); @@ -298,7 +298,7 @@ public DayOfMonth dayOfMonth() { * Creates new {@link AggregationExpression} that returns the day of the week for a date as a number between 1 * (Sunday) and 7 (Saturday). * - * @return + * @return new instance of {@link DayOfWeek}. */ public DayOfWeek dayOfWeek() { return applyTimezone(DayOfWeek.dayOfWeek(dateReference()), timezone); @@ -307,7 +307,7 @@ public DayOfWeek dayOfWeek() { /** * Creates new {@link AggregationExpression} that returns the year portion of a date. * - * @return + * @return new instance of {@link Year}. */ public Year year() { return applyTimezone(Year.year(dateReference()), timezone); @@ -316,7 +316,7 @@ public Year year() { /** * Creates new {@link AggregationExpression} that returns the month of a date as a number between 1 and 12. * - * @return + * @return new instance of {@link Month}. */ public Month month() { return applyTimezone(Month.month(dateReference()), timezone); @@ -326,7 +326,7 @@ public Month month() { * Creates new {@link AggregationExpression} that returns the week of the year for a date as a number between 0 and * 53. * - * @return + * @return new instance of {@link Week}. */ public Week week() { return applyTimezone(Week.week(dateReference()), timezone); @@ -335,7 +335,7 @@ public Week week() { /** * Creates new {@link AggregationExpression} that returns the hour portion of a date as a number between 0 and 23. * - * @return + * @return new instance of {@link Hour}. */ public Hour hour() { return applyTimezone(Hour.hour(dateReference()), timezone); @@ -344,7 +344,7 @@ public Hour hour() { /** * Creates new {@link AggregationExpression} that returns the minute portion of a date as a number between 0 and 59. * - * @return + * @return new instance of {@link Minute}. */ public Minute minute() { return applyTimezone(Minute.minute(dateReference()), timezone); @@ -354,7 +354,7 @@ public Minute minute() { * Creates new {@link AggregationExpression} that returns the second portion of a date as a number between 0 and 59, * but can be 60 to account for leap seconds. * - * @return + * @return new instance of {@link Second}. */ public Second second() { return applyTimezone(Second.second(dateReference()), timezone); @@ -364,7 +364,7 @@ public Second second() { * Creates new {@link AggregationExpression} that returns the millisecond portion of a date as an integer between 0 * and 999. * - * @return + * @return new instance of {@link Millisecond}. */ public Millisecond millisecond() { return applyTimezone(Millisecond.millisecond(dateReference()), timezone); @@ -375,7 +375,7 @@ public Millisecond millisecond() { * {@literal format}. * * @param format must not be {@literal null}. - * @return + * @return new instance of {@link DateToString}. */ public DateToString toString(String format) { return applyTimezone(DateToString.dateToString(dateReference()).toString(format), timezone); @@ -396,7 +396,7 @@ public DateToString toStringWithDefaultFormat() { * Creates new {@link AggregationExpression} that returns the weekday number in ISO 8601-2018 format, ranging from 1 * (for Monday) to 7 (for Sunday). * - * @return + * @return new instance of {@link IsoDayOfWeek}. */ public IsoDayOfWeek isoDayOfWeek() { return applyTimezone(IsoDayOfWeek.isoDayWeek(dateReference()), timezone); @@ -406,7 +406,7 @@ public IsoDayOfWeek isoDayOfWeek() { * Creates new {@link AggregationExpression} that returns the week number in ISO 8601-2018 format, ranging from 1 to * 53. * - * @return + * @return new instance of {@link IsoWeek}. */ public IsoWeek isoWeek() { return applyTimezone(IsoWeek.isoWeek(dateReference()), timezone); @@ -415,7 +415,7 @@ public IsoWeek isoWeek() { /** * Creates new {@link AggregationExpression} that returns the year number in ISO 8601-2018 format. * - * @return + * @return new instance of {@link IsoWeekYear}. */ public IsoWeekYear isoWeekYear() { return applyTimezone(IsoWeekYear.isoWeekYear(dateReference()), timezone); @@ -642,7 +642,7 @@ public static DayOfYear dayOfYear(Object value) { * Creates new {@link DayOfYear}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link DayOfYear}. */ public static DayOfYear dayOfYear(String fieldReference) { @@ -654,7 +654,7 @@ public static DayOfYear dayOfYear(String fieldReference) { * Creates new {@link DayOfYear}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link DayOfYear}. */ public static DayOfYear dayOfYear(AggregationExpression expression) { @@ -714,7 +714,7 @@ public static DayOfMonth dayOfMonth(Object value) { * Creates new {@link DayOfMonth}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link DayOfMonth}. */ public static DayOfMonth dayOfMonth(String fieldReference) { @@ -726,7 +726,7 @@ public static DayOfMonth dayOfMonth(String fieldReference) { * Creates new {@link DayOfMonth}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link DayOfMonth}. */ public static DayOfMonth dayOfMonth(AggregationExpression expression) { @@ -786,7 +786,7 @@ public static DayOfWeek dayOfWeek(Object value) { * Creates new {@link DayOfWeek}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link DayOfWeek}. */ public static DayOfWeek dayOfWeek(String fieldReference) { @@ -798,7 +798,7 @@ public static DayOfWeek dayOfWeek(String fieldReference) { * Creates new {@link DayOfWeek}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link DayOfWeek}. */ public static DayOfWeek dayOfWeek(AggregationExpression expression) { @@ -858,7 +858,7 @@ public static Year year(Object value) { * Creates new {@link Year}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Year}. */ public static Year yearOf(String fieldReference) { @@ -870,7 +870,7 @@ public static Year yearOf(String fieldReference) { * Creates new {@link Year}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Year}. */ public static Year yearOf(AggregationExpression expression) { @@ -930,7 +930,7 @@ public static Month month(Object value) { * Creates new {@link Month}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Month}. */ public static Month monthOf(String fieldReference) { @@ -942,7 +942,7 @@ public static Month monthOf(String fieldReference) { * Creates new {@link Month}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Month}. */ public static Month monthOf(AggregationExpression expression) { @@ -1002,7 +1002,7 @@ public static Week week(Object value) { * Creates new {@link Week}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Week}. */ public static Week weekOf(String fieldReference) { @@ -1014,7 +1014,7 @@ public static Week weekOf(String fieldReference) { * Creates new {@link Week}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Week}. */ public static Week weekOf(AggregationExpression expression) { @@ -1074,7 +1074,7 @@ public static Hour hour(Object value) { * Creates new {@link Hour}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Hour}. */ public static Hour hourOf(String fieldReference) { @@ -1086,7 +1086,7 @@ public static Hour hourOf(String fieldReference) { * Creates new {@link Hour}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Hour}. */ public static Hour hourOf(AggregationExpression expression) { @@ -1146,7 +1146,7 @@ public static Minute minute(Object value) { * Creates new {@link Minute}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Minute}. */ public static Minute minuteOf(String fieldReference) { @@ -1158,7 +1158,7 @@ public static Minute minuteOf(String fieldReference) { * Creates new {@link Minute}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Minute}. */ public static Minute minuteOf(AggregationExpression expression) { @@ -1218,7 +1218,7 @@ public static Second second(Object value) { * Creates new {@link Second}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Second}. */ public static Second secondOf(String fieldReference) { @@ -1230,7 +1230,7 @@ public static Second secondOf(String fieldReference) { * Creates new {@link Second}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Second}. */ public static Second secondOf(AggregationExpression expression) { @@ -1290,7 +1290,7 @@ public static Millisecond millisecond(Object value) { * Creates new {@link Millisecond}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Millisecond}. */ public static Millisecond millisecondOf(String fieldReference) { @@ -1302,7 +1302,7 @@ public static Millisecond millisecondOf(String fieldReference) { * Creates new {@link Millisecond}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Millisecond}. */ public static Millisecond millisecondOf(AggregationExpression expression) { @@ -1376,7 +1376,7 @@ public DateToString defaultFormat() { * Creates new {@link FormatBuilder} allowing to define the date format to apply. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link FormatBuilder} to crate {@link DateToString}. */ public static FormatBuilder dateOf(final String fieldReference) { @@ -1388,7 +1388,7 @@ public static FormatBuilder dateOf(final String fieldReference) { * Creates new {@link FormatBuilder} allowing to define the date format to apply. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link FormatBuilder} to crate {@link DateToString}. */ public static FormatBuilder dateOf(final AggregationExpression expression) { @@ -1540,7 +1540,7 @@ public static IsoDayOfWeek isoDayWeek(Object value) { * Creates new {@link IsoDayOfWeek}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IsoDayOfWeek}. */ public static IsoDayOfWeek isoDayOfWeek(String fieldReference) { @@ -1552,7 +1552,7 @@ public static IsoDayOfWeek isoDayOfWeek(String fieldReference) { * Creates new {@link IsoDayOfWeek}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IsoDayOfWeek}. */ public static IsoDayOfWeek isoDayOfWeek(AggregationExpression expression) { @@ -1612,7 +1612,7 @@ public static IsoWeek isoWeek(Object value) { * Creates new {@link IsoWeek}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IsoWeek}. */ public static IsoWeek isoWeekOf(String fieldReference) { @@ -1624,7 +1624,7 @@ public static IsoWeek isoWeekOf(String fieldReference) { * Creates new {@link IsoWeek}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IsoWeek}. */ public static IsoWeek isoWeekOf(AggregationExpression expression) { @@ -1684,7 +1684,7 @@ public static IsoWeekYear isoWeekYear(Object value) { * Creates new {@link IsoWeekYear}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IsoWeekYear}. */ public static IsoWeekYear isoWeekYearOf(String fieldReference) { @@ -1696,7 +1696,7 @@ public static IsoWeekYear isoWeekYearOf(String fieldReference) { * Creates new {@link Millisecond}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IsoWeekYear}. */ public static IsoWeekYear isoWeekYearOf(AggregationExpression expression) { @@ -2378,6 +2378,7 @@ protected String getMongoMethod() { @SuppressWarnings("unchecked") private static T applyTimezone(T instance, Timezone timezone) { return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone() - ? (T) instance.withTimezone(timezone) : instance; + ? (T) instance.withTimezone(timezone) + : instance; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java index 21d2d24be5..fa09bf3028 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java @@ -46,7 +46,7 @@ public final class ExposedFields implements Iterable { /** * Returns an empty {@link ExposedFields} instance. * - * @return + * @return never {@literal null}. * @since 2.0 */ public static ExposedFields empty() { @@ -57,7 +57,7 @@ public static ExposedFields empty() { * Creates a new {@link ExposedFields} instance from the given {@link ExposedField}s. * * @param fields must not be {@literal null}. - * @return + * @return never {@literal null}. */ public static ExposedFields from(ExposedField... fields) { return from(Arrays.asList(fields)); @@ -67,7 +67,7 @@ public static ExposedFields from(ExposedField... fields) { * Creates a new {@link ExposedFields} instance from the given {@link ExposedField}s. * * @param fields must not be {@literal null}. - * @return + * @return never {@literal null}. */ private static ExposedFields from(List fields) { @@ -84,7 +84,7 @@ private static ExposedFields from(List fields) { * Creates synthetic {@link ExposedFields} from the given {@link Fields}. * * @param fields must not be {@literal null}. - * @return + * @return never {@literal null}. */ public static ExposedFields synthetic(Fields fields) { return createFields(fields, true); @@ -94,7 +94,7 @@ public static ExposedFields synthetic(Fields fields) { * Creates non-synthetic {@link ExposedFields} from the given {@link Fields}. * * @param fields must not be {@literal null}. - * @return + * @return never {@literal null}. */ public static ExposedFields nonSynthetic(Fields fields) { return createFields(fields, false); @@ -105,7 +105,7 @@ public static ExposedFields nonSynthetic(Fields fields) { * * @param fields must not be {@literal null}. * @param synthetic - * @return + * @return never {@literal null}. */ private static ExposedFields createFields(Fields fields, boolean synthetic) { @@ -135,7 +135,7 @@ private ExposedFields(List originals, List synthetic * Creates a new {@link ExposedFields} adding the given {@link ExposedField}. * * @param field must not be {@literal null}. - * @return + * @return new instance of {@link ExposedFields}. */ public ExposedFields and(ExposedField field) { @@ -151,8 +151,8 @@ public ExposedFields and(ExposedField field) { /** * Returns the field with the given name or {@literal null} if no field with the given name is available. * - * @param name - * @return + * @param name must not be {@literal null}. + * @return can be {@literal null}. */ @Nullable public ExposedField getField(String name) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java index 0cee343733..dc047ab874 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java @@ -146,7 +146,7 @@ public interface FromBuilder { * Set the {@literal collectionName} to apply the {@code $graphLookup} to. * * @param collectionName must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ StartWithBuilder from(String collectionName); } @@ -161,7 +161,7 @@ public interface StartWithBuilder { * Set the startWith {@literal fieldReferences} to apply the {@code $graphLookup} to. * * @param fieldReferences must not be {@literal null}. - * @return + * @return never {@literal null}. */ ConnectFromBuilder startWith(String... fieldReferences); @@ -169,7 +169,7 @@ public interface StartWithBuilder { * Set the startWith {@literal expressions} to apply the {@code $graphLookup} to. * * @param expressions must not be {@literal null}. - * @return + * @return never {@literal null}. */ ConnectFromBuilder startWith(AggregationExpression... expressions); @@ -178,7 +178,7 @@ public interface StartWithBuilder { * {@link AggregationExpression} to apply the {@code $graphLookup} to. * * @param expressions must not be {@literal null}. - * @return + * @return never {@literal null}. * @throws IllegalArgumentException */ ConnectFromBuilder startWith(Object... expressions); @@ -193,7 +193,7 @@ public interface ConnectFromBuilder { * Set the connectFrom {@literal fieldName} to apply the {@code $graphLookup} to. * * @param fieldName must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ ConnectToBuilder connectFrom(String fieldName); } @@ -207,7 +207,7 @@ public interface ConnectToBuilder { * Set the connectTo {@literal fieldName} to apply the {@code $graphLookup} to. * * @param fieldName must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ GraphLookupOperationBuilder connectTo(String fieldName); } @@ -360,7 +360,7 @@ protected GraphLookupOperationBuilder(String from, List startW * Optionally limit the number of recursions. * * @param numberOfRecursions must be greater or equal to zero. - * @return + * @return this. */ public GraphLookupOperationBuilder maxDepth(long numberOfRecursions) { @@ -374,7 +374,7 @@ public GraphLookupOperationBuilder maxDepth(long numberOfRecursions) { * Optionally add a depth field {@literal fieldName} to each traversed document in the search path. * * @param fieldName must not be {@literal null} or empty. - * @return + * @return this. */ public GraphLookupOperationBuilder depthField(String fieldName) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java index 05913eb60d..cddd94d254 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java @@ -89,7 +89,7 @@ public Document toDocument(AggregationOperationContext context) { /** * Get a builder that allows creation of {@link LookupOperation}. * - * @return + * @return never {@literal null}. */ public static FromBuilder newLookup() { return new LookupOperationBuilder(); @@ -99,7 +99,7 @@ public static interface FromBuilder { /** * @param name the collection in the same database to perform the join with, must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ LocalFieldBuilder from(String name); } @@ -109,7 +109,7 @@ public static interface LocalFieldBuilder { /** * @param name the field from the documents input to the {@code $lookup} stage, must not be {@literal null} or * empty. - * @return + * @return never {@literal null}. */ ForeignFieldBuilder localField(String name); } @@ -118,7 +118,7 @@ public static interface ForeignFieldBuilder { /** * @param name the field from the documents in the {@code from} collection, must not be {@literal null} or empty. - * @return + * @return never {@literal null}. */ AsBuilder foreignField(String name); } @@ -127,7 +127,7 @@ public static interface AsBuilder { /** * @param name the name of the new array field to add to the input documents, must not be {@literal null} or empty. - * @return + * @return new instance of {@link LookupOperation}. */ LookupOperation as(String name); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java index cae54d3944..b052874953 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java @@ -186,7 +186,7 @@ public static UniqueMergeId ofIdFields(String... fields) { /** * Merge Documents by using the MongoDB {@literal _id} field. * - * @return + * @return never {@literal null}. */ public static UniqueMergeId id() { return ID; @@ -375,7 +375,7 @@ private WhenDocumentsDontMatch(String value) { /** * Factory method creating {@link WhenDocumentsDontMatch} from a {@code value} literal. * - * @param value + * @param value must not be {@literal null}. * @return new instance of {@link WhenDocumentsDontMatch}. */ public static WhenDocumentsDontMatch whenNotMatchedOf(String value) { @@ -403,7 +403,7 @@ public static WhenDocumentsDontMatch discardDocument() { /** * Stop and fail the aggregation operation. Does not revert already performed changes on previous documents. * - * @return + * @return new instance of {@link WhenDocumentsDontMatch}. */ public static WhenDocumentsDontMatch failWhenNotMatch() { return whenNotMatchedOf("fail"); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index 0bf5341c37..e109d78484 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -346,7 +346,7 @@ protected ReplacementDocument() { /** * Creates a {@link ReplacementDocument} given {@link ReplacementContributor}. * - * @param contributor + * @param contributor must not be {@literal null}. */ protected ReplacementDocument(ReplacementContributor contributor) { @@ -362,7 +362,7 @@ private ReplacementDocument(Collection replacements) { * Creates a {@link ReplacementDocument} given a {@literal value}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link ReplacementDocument}. */ public static ReplacementDocument valueOf(Object value) { return new ReplacementDocument(new DocumentContributor(value)); @@ -372,7 +372,7 @@ public static ReplacementDocument valueOf(Object value) { * Creates a {@link ReplacementDocument} given a single {@literal field} and {@link AggregationExpression}. * * @param aggregationExpression must not be {@literal null}. - * @return + * @return new instance of {@link ReplacementDocument}. */ public static ReplacementDocument forExpression(String field, AggregationExpression aggregationExpression) { return new ReplacementDocument(new ExpressionFieldContributor(Fields.field(field), aggregationExpression)); @@ -382,7 +382,7 @@ public static ReplacementDocument forExpression(String field, AggregationExpress * Creates a {@link ReplacementDocument} given a single {@literal field} and {@literal value}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link ReplacementDocument}. */ public static ReplacementDocument forSingleValue(String field, Object value) { return new ReplacementDocument(new ValueFieldContributor(Fields.field(field), value)); @@ -438,7 +438,7 @@ private interface ReplacementContributor extends AggregationExpression { * {@link AggregationOperationContext}. * * @param context will never be {@literal null}. - * @return + * @return never {@literal null}. */ Document toDocument(AggregationOperationContext context); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java index 60bdcdc3ae..9fb7249e4b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java @@ -57,7 +57,7 @@ public static ReplaceWithOperation replaceWithValue(Object value) { * {@link Field field reference}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link ReplaceWithOperation}. */ public static ReplaceWithOperation replaceWithValueOf(Object value) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java index b26ad24c26..874ce71893 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java @@ -34,7 +34,7 @@ public class SetOperators { * Take the array referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link SetOperatorFactory}. */ public static SetOperatorFactory arrayAsSet(String fieldReference) { return new SetOperatorFactory(fieldReference); @@ -44,7 +44,7 @@ public static SetOperatorFactory arrayAsSet(String fieldReference) { * Take the array resulting from the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetOperatorFactory}. */ public static SetOperatorFactory arrayAsSet(AggregationExpression expression) { return new SetOperatorFactory(expression); @@ -87,7 +87,7 @@ public SetOperatorFactory(AggregationExpression expression) { * returns {@literal true} if they have the same distinct elements and {@literal false} otherwise. * * @param arrayReferences must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public SetEquals isEqualTo(String... arrayReferences) { return createSetEquals().isEqualTo(arrayReferences); @@ -98,7 +98,7 @@ public SetEquals isEqualTo(String... arrayReferences) { * returns {@literal true} if they have the same distinct elements and {@literal false} otherwise. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public SetEquals isEqualTo(AggregationExpression... expressions) { return createSetEquals().isEqualTo(expressions); @@ -113,7 +113,7 @@ private SetEquals createSetEquals() { * arrays and returns an array that contains the elements that appear in every of those. * * @param arrayReferences must not be {@literal null}. - * @return + * @return new instance of {@link SetIntersection}. */ public SetIntersection intersects(String... arrayReferences) { return createSetIntersection().intersects(arrayReferences); @@ -124,7 +124,7 @@ public SetIntersection intersects(String... arrayReferences) { * arrays and returns an array that contains the elements that appear in every of those. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link SetIntersection}. */ public SetIntersection intersects(AggregationExpression... expressions) { return createSetIntersection().intersects(expressions); @@ -139,7 +139,7 @@ private SetIntersection createSetIntersection() { * arrays and returns an array that contains the elements that appear in any of those. * * @param arrayReferences must not be {@literal null}. - * @return + * @return new instance of {@link SetUnion}. */ public SetUnion union(String... arrayReferences) { return createSetUnion().union(arrayReferences); @@ -150,7 +150,7 @@ public SetUnion union(String... arrayReferences) { * arrays and returns an array that contains the elements that appear in any of those. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link SetUnion}. */ public SetUnion union(AggregationExpression... expressions) { return createSetUnion().union(expressions); @@ -165,7 +165,7 @@ private SetUnion createSetUnion() { * containing the elements that do not exist in the given {@literal arrayReference}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetDifference}. */ public SetDifference differenceTo(String arrayReference) { return createSetDifference().differenceTo(arrayReference); @@ -176,7 +176,7 @@ public SetDifference differenceTo(String arrayReference) { * containing the elements that do not exist in the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetDifference}. */ public SetDifference differenceTo(AggregationExpression expression) { return createSetDifference().differenceTo(expression); @@ -191,7 +191,7 @@ private SetDifference createSetDifference() { * {@literal true} if it is a subset of the given {@literal arrayReference}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetIsSubset}. */ public SetIsSubset isSubsetOf(String arrayReference) { return createSetIsSubset().isSubsetOf(arrayReference); @@ -202,7 +202,7 @@ public SetIsSubset isSubsetOf(String arrayReference) { * {@literal true} if it is a subset of the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetIsSubset}. */ public SetIsSubset isSubsetOf(AggregationExpression expression) { return createSetIsSubset().isSubsetOf(expression); @@ -216,7 +216,7 @@ private SetIsSubset createSetIsSubset() { * Creates new {@link AggregationExpression} that takes array of the previously mentioned field and returns * {@literal true} if any of the elements are {@literal true} and {@literal false} otherwise. * - * @return + * @return new instance of {@link AnyElementTrue}. */ public AnyElementTrue anyElementTrue() { return usesFieldRef() ? AnyElementTrue.arrayAsSet(fieldReference) : AnyElementTrue.arrayAsSet(expression); @@ -226,7 +226,7 @@ public AnyElementTrue anyElementTrue() { * Creates new {@link AggregationExpression} that tkes array of the previously mentioned field and returns * {@literal true} if no elements is {@literal false}. * - * @return + * @return new instance of {@link AllElementsTrue}. */ public AllElementsTrue allElementsTrue() { return usesFieldRef() ? AllElementsTrue.arrayAsSet(fieldReference) : AllElementsTrue.arrayAsSet(expression); @@ -257,7 +257,7 @@ protected String getMongoMethod() { * Create new {@link SetEquals}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public static SetEquals arrayAsSet(String arrayReference) { @@ -269,7 +269,7 @@ public static SetEquals arrayAsSet(String arrayReference) { * Create new {@link SetEquals}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public static SetEquals arrayAsSet(AggregationExpression expression) { @@ -281,7 +281,7 @@ public static SetEquals arrayAsSet(AggregationExpression expression) { * Creates new {@link java.util.Set} with all previously added arguments appending the given one. * * @param arrayReferences must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public SetEquals isEqualTo(String... arrayReferences) { @@ -293,7 +293,7 @@ public SetEquals isEqualTo(String... arrayReferences) { * Creates new {@link Sum} with all previously added arguments appending the given one. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public SetEquals isEqualTo(AggregationExpression... expressions) { @@ -305,7 +305,7 @@ public SetEquals isEqualTo(AggregationExpression... expressions) { * Creates new {@link Sum} with all previously added arguments appending the given one. * * @param array must not be {@literal null}. - * @return + * @return new instance of {@link SetEquals}. */ public SetEquals isEqualTo(Object[] array) { @@ -334,7 +334,7 @@ protected String getMongoMethod() { * Creates new {@link SetIntersection} * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetIntersection}. */ public static SetIntersection arrayAsSet(String arrayReference) { @@ -346,7 +346,7 @@ public static SetIntersection arrayAsSet(String arrayReference) { * Creates new {@link SetIntersection}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetIntersection}. */ public static SetIntersection arrayAsSet(AggregationExpression expression) { @@ -358,7 +358,7 @@ public static SetIntersection arrayAsSet(AggregationExpression expression) { * Creates new {@link SetIntersection} with all previously added arguments appending the given one. * * @param arrayReferences must not be {@literal null}. - * @return + * @return new instance of {@link SetIntersection}. */ public SetIntersection intersects(String... arrayReferences) { @@ -370,7 +370,7 @@ public SetIntersection intersects(String... arrayReferences) { * Creates new {@link SetIntersection} with all previously added arguments appending the given one. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link SetIntersection}. */ public SetIntersection intersects(AggregationExpression... expressions) { @@ -399,7 +399,7 @@ protected String getMongoMethod() { * Creates new {@link SetUnion}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetUnion}. */ public static SetUnion arrayAsSet(String arrayReference) { @@ -411,7 +411,7 @@ public static SetUnion arrayAsSet(String arrayReference) { * Creates new {@link SetUnion}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetUnion}. */ public static SetUnion arrayAsSet(AggregationExpression expression) { @@ -423,7 +423,7 @@ public static SetUnion arrayAsSet(AggregationExpression expression) { * Creates new {@link SetUnion} with all previously added arguments appending the given one. * * @param arrayReferences must not be {@literal null}. - * @return + * @return new instance of {@link SetUnion}. */ public SetUnion union(String... arrayReferences) { @@ -435,7 +435,7 @@ public SetUnion union(String... arrayReferences) { * Creates new {@link SetUnion} with all previously added arguments appending the given one. * * @param expressions must not be {@literal null}. - * @return + * @return new instance of {@link SetUnion}. */ public SetUnion union(AggregationExpression... expressions) { @@ -464,7 +464,7 @@ protected String getMongoMethod() { * Creates new {@link SetDifference}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetDifference}. */ public static SetDifference arrayAsSet(String arrayReference) { @@ -476,7 +476,7 @@ public static SetDifference arrayAsSet(String arrayReference) { * Creates new {@link SetDifference}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetDifference}. */ public static SetDifference arrayAsSet(AggregationExpression expression) { @@ -488,7 +488,7 @@ public static SetDifference arrayAsSet(AggregationExpression expression) { * Creates new {@link SetDifference} with all previously added arguments appending the given one. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetDifference}. */ public SetDifference differenceTo(String arrayReference) { @@ -500,7 +500,7 @@ public SetDifference differenceTo(String arrayReference) { * Creates new {@link SetDifference} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetDifference}. */ public SetDifference differenceTo(AggregationExpression expression) { @@ -529,7 +529,7 @@ protected String getMongoMethod() { * Creates new {@link SetIsSubset}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetIsSubset}. */ public static SetIsSubset arrayAsSet(String arrayReference) { @@ -541,7 +541,7 @@ public static SetIsSubset arrayAsSet(String arrayReference) { * Creates new {@link SetIsSubset}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetIsSubset}. */ public static SetIsSubset arrayAsSet(AggregationExpression expression) { @@ -553,7 +553,7 @@ public static SetIsSubset arrayAsSet(AggregationExpression expression) { * Creates new {@link SetIsSubset} with all previously added arguments appending the given one. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link SetIsSubset}. */ public SetIsSubset isSubsetOf(String arrayReference) { @@ -565,7 +565,7 @@ public SetIsSubset isSubsetOf(String arrayReference) { * Creates new {@link SetIsSubset} with all previously added arguments appending the given one. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SetIsSubset}. */ public SetIsSubset isSubsetOf(AggregationExpression expression) { @@ -594,7 +594,7 @@ protected String getMongoMethod() { * Creates new {@link AnyElementTrue}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link AnyElementTrue}. */ public static AnyElementTrue arrayAsSet(String arrayReference) { @@ -606,7 +606,7 @@ public static AnyElementTrue arrayAsSet(String arrayReference) { * Creates new {@link AnyElementTrue}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link AnyElementTrue}. */ public static AnyElementTrue arrayAsSet(AggregationExpression expression) { @@ -639,7 +639,7 @@ protected String getMongoMethod() { * Creates new {@link AllElementsTrue}. * * @param arrayReference must not be {@literal null}. - * @return + * @return new instance of {@link AllElementsTrue}. */ public static AllElementsTrue arrayAsSet(String arrayReference) { @@ -651,7 +651,7 @@ public static AllElementsTrue arrayAsSet(String arrayReference) { * Creates new {@link AllElementsTrue}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link AllElementsTrue}. */ public static AllElementsTrue arrayAsSet(AggregationExpression expression) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java index 3187648450..d97ed924b7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java @@ -35,7 +35,7 @@ public class StringOperators { * Take the array referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StringOperatorFactory}. */ public static StringOperatorFactory valueOf(String fieldReference) { return new StringOperatorFactory(fieldReference); @@ -45,7 +45,7 @@ public static StringOperatorFactory valueOf(String fieldReference) { * Take the array referenced by given {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StringOperatorFactory}. */ public static StringOperatorFactory valueOf(AggregationExpression fieldReference) { return new StringOperatorFactory(fieldReference); @@ -88,7 +88,7 @@ public StringOperatorFactory(AggregationExpression expression) { * of the referenced field to it. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Concat}. */ public Concat concatValueOf(String fieldReference) { @@ -101,7 +101,7 @@ public Concat concatValueOf(String fieldReference) { * of the given {@link AggregationExpression} to it. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Concat}. */ public Concat concatValueOf(AggregationExpression expression) { @@ -114,7 +114,7 @@ public Concat concatValueOf(AggregationExpression expression) { * {@literal value} to it. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Concat}. */ public Concat concat(String value) { @@ -130,8 +130,8 @@ private Concat createConcat() { * Creates new {@link AggregationExpression} that takes the associated string representation and returns a substring * starting at a specified index position. * - * @param start - * @return + * @param start start index number (including) + * @return new instance of {@link Substr}. */ public Substr substring(int start) { return substring(start, -1); @@ -141,9 +141,9 @@ public Substr substring(int start) { * Creates new {@link AggregationExpression} that takes the associated string representation and returns a substring * starting at a specified index position including the specified number of characters. * - * @param start - * @param nrOfChars - * @return + * @param start start index number (including) + * @param nrOfChars number of characters. + * @return new instance of {@link Substr}. */ public Substr substring(int start, int nrOfChars) { return createSubstr().substring(start, nrOfChars); @@ -156,7 +156,7 @@ private Substr createSubstr() { /** * Creates new {@link AggregationExpression} that takes the associated string representation and lowers it. * - * @return + * @return new instance of {@link ToLower}. */ public ToLower toLower() { return usesFieldRef() ? ToLower.lowerValueOf(fieldReference) : ToLower.lowerValueOf(expression); @@ -165,7 +165,7 @@ public ToLower toLower() { /** * Creates new {@link AggregationExpression} that takes the associated string representation and uppers it. * - * @return + * @return new instance of {@link ToUpper}. */ public ToUpper toUpper() { return usesFieldRef() ? ToUpper.upperValueOf(fieldReference) : ToUpper.upperValueOf(expression); @@ -176,7 +176,7 @@ public ToUpper toUpper() { * case-insensitive comparison to the given {@literal value}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link StrCaseCmp}. */ public StrCaseCmp strCaseCmp(String value) { @@ -189,7 +189,7 @@ public StrCaseCmp strCaseCmp(String value) { * case-insensitive comparison to the referenced {@literal fieldReference}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StrCaseCmp}. */ public StrCaseCmp strCaseCmpValueOf(String fieldReference) { @@ -202,7 +202,7 @@ public StrCaseCmp strCaseCmpValueOf(String fieldReference) { * case-insensitive comparison to the result of the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StrCaseCmp}. */ public StrCaseCmp strCaseCmpValueOf(AggregationExpression expression) { @@ -220,7 +220,7 @@ private StrCaseCmp createStrCaseCmp() { * occurrence. * * @param substring must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes indexOf(String substring) { @@ -234,7 +234,7 @@ public IndexOfBytes indexOf(String substring) { * index (zero-based) of the first occurrence. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes indexOf(Field fieldReference) { @@ -248,7 +248,7 @@ public IndexOfBytes indexOf(Field fieldReference) { * byte index (zero-based) of the first occurrence. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes indexOf(AggregationExpression expression) { @@ -266,7 +266,7 @@ private IndexOfBytes.SubstringBuilder createIndexOfBytesSubstringBuilder() { * first occurrence. * * @param substring must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public IndexOfCP indexOfCP(String substring) { @@ -280,7 +280,7 @@ public IndexOfCP indexOfCP(String substring) { * point index (zero-based) of the first occurrence. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public IndexOfCP indexOfCP(Field fieldReference) { @@ -294,7 +294,7 @@ public IndexOfCP indexOfCP(Field fieldReference) { * code point index (zero-based) of the first occurrence. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public IndexOfCP indexOfCP(AggregationExpression expression) { @@ -311,7 +311,7 @@ private IndexOfCP.SubstringBuilder createIndexOfCPSubstringBuilder() { * substrings based on the given delimiter. * * @param delimiter must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public Split split(String delimiter) { return createSplit().split(delimiter); @@ -322,7 +322,7 @@ public Split split(String delimiter) { * substrings based on the delimiter resulting from the referenced field.. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public Split split(Field fieldReference) { return createSplit().split(fieldReference); @@ -333,7 +333,7 @@ public Split split(Field fieldReference) { * substrings based on a delimiter resulting from the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public Split split(AggregationExpression expression) { return createSplit().split(expression); @@ -347,7 +347,7 @@ private Split createSplit() { * Creates new {@link AggregationExpression} that returns the number of UTF-8 bytes in the associated string * representation. * - * @return + * @return new instance of {@link StrLenBytes}. */ public StrLenBytes length() { return usesFieldRef() ? StrLenBytes.stringLengthOf(fieldReference) : StrLenBytes.stringLengthOf(expression); @@ -357,7 +357,7 @@ public StrLenBytes length() { * Creates new {@link AggregationExpression} that returns the number of UTF-8 code points in the associated string * representation. * - * @return + * @return new instance of {@link StrLenCP}. */ public StrLenCP lengthCP() { return usesFieldRef() ? StrLenCP.stringLengthOfCP(fieldReference) : StrLenCP.stringLengthOfCP(expression); @@ -368,7 +368,7 @@ public StrLenCP lengthCP() { * starting at a specified code point index position. * * @param codePointStart - * @return + * @return new instance of {@link SubstrCP}. */ public SubstrCP substringCP(int codePointStart) { return substringCP(codePointStart, -1); @@ -378,9 +378,9 @@ public SubstrCP substringCP(int codePointStart) { * Creates new {@link AggregationExpression} that takes the associated string representation and returns a substring * starting at a specified code point index position including the specified number of code points. * - * @param codePointStart + * @param codePointStart start point (including). * @param nrOfCodePoints - * @return + * @return new instance of {@link SubstrCP}. */ public SubstrCP substringCP(int codePointStart, int nrOfCodePoints) { return createSubstrCP().substringCP(codePointStart, nrOfCodePoints); @@ -541,7 +541,7 @@ protected String getMongoMethod() { * Creates new {@link Concat}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Concat}. */ public static Concat valueOf(String fieldReference) { @@ -553,7 +553,7 @@ public static Concat valueOf(String fieldReference) { * Creates new {@link Concat}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Concat}. */ public static Concat valueOf(AggregationExpression expression) { @@ -565,7 +565,7 @@ public static Concat valueOf(AggregationExpression expression) { * Creates new {@link Concat}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link Concat}. */ public static Concat stringValue(String value) { @@ -573,18 +573,36 @@ public static Concat stringValue(String value) { return new Concat(Collections.singletonList(value)); } + /** + * Concat the value of the given field. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Concat}. + */ public Concat concatValueOf(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new Concat(append(Fields.field(fieldReference))); } + /** + * Concat the value resulting from the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Concat}. + */ public Concat concatValueOf(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); return new Concat(append(expression)); } + /** + * Concat the given value. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Concat}. + */ public Concat concat(String value) { return new Concat(append(value)); } @@ -610,7 +628,7 @@ protected String getMongoMethod() { * Creates new {@link Substr}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Substr}. */ public static Substr valueOf(String fieldReference) { @@ -622,7 +640,7 @@ public static Substr valueOf(String fieldReference) { * Creates new {@link Substr}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Substr}. */ public static Substr valueOf(AggregationExpression expression) { @@ -630,10 +648,19 @@ public static Substr valueOf(AggregationExpression expression) { return new Substr(Collections.singletonList(expression)); } + /** + * @param start start index (including) + * @return new instance of {@link Substr}. + */ public Substr substring(int start) { return substring(start, -1); } + /** + * @param start start index (including) + * @param nrOfChars + * @return new instance of {@link Substr}. + */ public Substr substring(int start, int nrOfChars) { return new Substr(append(Arrays.asList(start, nrOfChars))); } @@ -777,7 +804,7 @@ public static StrCaseCmp valueOf(String fieldReference) { * Creates new {@link StrCaseCmp}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StrCaseCmp}. */ public static StrCaseCmp valueOf(AggregationExpression expression) { @@ -789,7 +816,7 @@ public static StrCaseCmp valueOf(AggregationExpression expression) { * Creates new {@link StrCaseCmp}. * * @param value must not be {@literal null}. - * @return + * @return new instance of {@link StrCaseCmp}. */ public static StrCaseCmp stringValue(String value) { @@ -834,7 +861,7 @@ protected String getMongoMethod() { * Start creating a new {@link IndexOfBytes}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link SubstringBuilder}. */ public static SubstringBuilder valueOf(String fieldReference) { @@ -846,7 +873,7 @@ public static SubstringBuilder valueOf(String fieldReference) { * Start creating a new {@link IndexOfBytes}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SubstringBuilder}. */ public static SubstringBuilder valueOf(AggregationExpression expression) { @@ -858,7 +885,7 @@ public static SubstringBuilder valueOf(AggregationExpression expression) { * Optionally define the substring search start and end position. * * @param range must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes within(Range range) { return new IndexOfBytes(append(AggregationUtils.toRangeValues(range))); @@ -876,7 +903,7 @@ private SubstringBuilder(Object stringExpression) { * Creates a new {@link IndexOfBytes} given {@literal substring}. * * @param substring must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes indexOf(String substring) { return new IndexOfBytes(Arrays.asList(stringExpression, substring)); @@ -886,7 +913,7 @@ public IndexOfBytes indexOf(String substring) { * Creates a new {@link IndexOfBytes} given {@link AggregationExpression} that resolves to the substring. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes indexOf(AggregationExpression expression) { return new IndexOfBytes(Arrays.asList(stringExpression, expression)); @@ -896,7 +923,7 @@ public IndexOfBytes indexOf(AggregationExpression expression) { * Creates a new {@link IndexOfBytes} given {@link Field} that resolves to the substring. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfBytes}. */ public IndexOfBytes indexOf(Field fieldReference) { return new IndexOfBytes(Arrays.asList(stringExpression, fieldReference)); @@ -924,7 +951,7 @@ protected String getMongoMethod() { * Start creating a new {@link IndexOfCP}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public static SubstringBuilder valueOf(String fieldReference) { @@ -936,7 +963,7 @@ public static SubstringBuilder valueOf(String fieldReference) { * Start creating a new {@link IndexOfCP}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public static SubstringBuilder valueOf(AggregationExpression expression) { @@ -948,7 +975,7 @@ public static SubstringBuilder valueOf(AggregationExpression expression) { * Optionally define the substring search start and end position. * * @param range must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public IndexOfCP within(Range range) { return new IndexOfCP(append(AggregationUtils.toRangeValues(range))); @@ -966,7 +993,7 @@ private SubstringBuilder(Object stringExpression) { * Creates a new {@link IndexOfCP} given {@literal substring}. * * @param substring must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public IndexOfCP indexOf(String substring) { return new IndexOfCP(Arrays.asList(stringExpression, substring)); @@ -976,7 +1003,7 @@ public IndexOfCP indexOf(String substring) { * Creates a new {@link IndexOfCP} given {@link AggregationExpression} that resolves to the substring. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link IndexOfCP}. */ public IndexOfCP indexOf(AggregationExpression expression) { return new IndexOfCP(Arrays.asList(stringExpression, expression)); @@ -1014,7 +1041,7 @@ protected String getMongoMethod() { * Start creating a new {@link Split}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public static Split valueOf(String fieldReference) { @@ -1026,7 +1053,7 @@ public static Split valueOf(String fieldReference) { * Start creating a new {@link Split}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public static Split valueOf(AggregationExpression expression) { @@ -1038,7 +1065,7 @@ public static Split valueOf(AggregationExpression expression) { * Use given {@link String} as delimiter. * * @param delimiter must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public Split split(String delimiter) { @@ -1050,7 +1077,7 @@ public Split split(String delimiter) { * Use value of referenced field as delimiter. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public Split split(Field fieldReference) { @@ -1062,7 +1089,7 @@ public Split split(Field fieldReference) { * Use value resulting from {@link AggregationExpression} as delimiter. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link Split}. */ public Split split(AggregationExpression expression) { @@ -1091,7 +1118,7 @@ protected String getMongoMethod() { * Creates new {@link StrLenBytes}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StrLenBytes}. */ public static StrLenBytes stringLengthOf(String fieldReference) { return new StrLenBytes(Fields.field(fieldReference)); @@ -1101,7 +1128,7 @@ public static StrLenBytes stringLengthOf(String fieldReference) { * Creates new {@link StrLenBytes}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StrLenBytes}. */ public static StrLenBytes stringLengthOf(AggregationExpression expression) { @@ -1130,7 +1157,7 @@ protected String getMongoMethod() { * Creates new {@link StrLenCP}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link StrLenCP}. */ public static StrLenCP stringLengthOfCP(String fieldReference) { return new StrLenCP(Fields.field(fieldReference)); @@ -1140,7 +1167,7 @@ public static StrLenCP stringLengthOfCP(String fieldReference) { * Creates new {@link StrLenCP}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link StrLenCP}. */ public static StrLenCP stringLengthOfCP(AggregationExpression expression) { @@ -1169,7 +1196,7 @@ protected String getMongoMethod() { * Creates new {@link SubstrCP}. * * @param fieldReference must not be {@literal null}. - * @return + * @return new instance of {@link SubstrCP}. */ public static SubstrCP valueOf(String fieldReference) { @@ -1181,7 +1208,7 @@ public static SubstrCP valueOf(String fieldReference) { * Creates new {@link SubstrCP}. * * @param expression must not be {@literal null}. - * @return + * @return new instance of {@link SubstrCP}. */ public static SubstrCP valueOf(AggregationExpression expression) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java index d4546b9e10..3233c30233 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java @@ -72,7 +72,7 @@ public void setCustomConversions(CustomConversions conversions) { /** * Registers {@link EntityInstantiators} to customize entity instantiation. * - * @param instantiators + * @param instantiators can be {@literal null}. Uses default {@link EntityInstantiators} if so. */ public void setInstantiators(@Nullable EntityInstantiators instantiators) { this.instantiators = instantiators == null ? new EntityInstantiators() : instantiators; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java index 2f0569bd47..41066052d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java @@ -46,7 +46,7 @@ public class CustomConversions extends MongoCustomConversions { /** * Creates a new {@link CustomConversions} instance registering the given converters. * - * @param converters + * @param converters must not be {@literal null}. */ public CustomConversions(List converters) { super(converters); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java index 04ddc97115..18b2695e92 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java @@ -45,7 +45,7 @@ public interface DbRefResolver { * @param property will never be {@literal null}. * @param dbref the {@link DBRef} to resolve. * @param callback will never be {@literal null}. - * @return + * @return can be {@literal null}. */ @Nullable Object resolveDbRef(MongoPersistentProperty property, @Nullable DBRef dbref, DbRefResolverCallback callback, @@ -58,7 +58,7 @@ Object resolveDbRef(MongoPersistentProperty property, @Nullable DBRef dbref, DbR * @param annotation will never be {@literal null}. * @param entity will never be {@literal null}. * @param id will never be {@literal null}. - * @return + * @return new instance of {@link DBRef}. */ default DBRef createDbRef(@Nullable org.springframework.data.mongodb.core.mapping.DBRef annotation, MongoPersistentEntity entity, Object id) { @@ -74,7 +74,7 @@ default DBRef createDbRef(@Nullable org.springframework.data.mongodb.core.mappin * Actually loads the {@link DBRef} from the datasource. * * @param dbRef must not be {@literal null}. - * @return + * @return can be {@literal null}. * @since 1.7 */ @Nullable 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 fe3ac71fbd..606221deb4 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 @@ -23,7 +23,6 @@ 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; @@ -42,9 +41,7 @@ /** * Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type - * information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String} - * conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)} - * respectively. + * information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}. * * @author Oliver Gierke * @author Thomas Darimont @@ -111,7 +108,7 @@ public DefaultMongoTypeMapper(@Nullable String typeKey, * {@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 + * @param mappers must not be {@literal null}. */ public DefaultMongoTypeMapper(@Nullable String typeKey, List mappers) { this(typeKey, new DocumentTypeAliasAccessor(typeKey), null, mappers); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java index 5709976176..9522a60ce6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java @@ -70,10 +70,10 @@ Bson getDocument() { /** * Puts the given value into the backing {@link Document} based on the coordinates defined through the given * {@link MongoPersistentProperty}. By default this will be the plain field name. But field names might also consist - * of path traversals so we might need to create intermediate {@link BasicDocument}s. + * of path traversals so we might need to create intermediate {@link Document}s. * * @param prop must not be {@literal null}. - * @param value + * @param value can be {@literal null}. */ public void put(MongoPersistentProperty prop, @Nullable Object value) { @@ -106,7 +106,7 @@ public void put(MongoPersistentProperty prop, @Nullable Object value) { * a path expression in the field name metadata. * * @param property must not be {@literal null}. - * @return + * @return can be {@literal null}. */ @Nullable public Object get(MongoPersistentProperty property) { @@ -150,7 +150,7 @@ public Object getRawId(MongoPersistentEntity entity) { * {@link MongoPersistentProperty}. * * @param property must not be {@literal null}. - * @return + * @return {@literal true} if no non {@literal null} value present. */ @SuppressWarnings("unchecked") public boolean hasValue(MongoPersistentProperty property) { @@ -203,7 +203,7 @@ public boolean hasValue(MongoPersistentProperty property) { * Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise. * * @param source can be {@literal null}. - * @return + * @return can be {@literal null}. */ @Nullable @SuppressWarnings("unchecked") diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java index 1b00add6b6..4437a95d3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java @@ -91,7 +91,7 @@ private GeoConverters() {} /** * Returns the geo converters to be registered. * - * @return + * @return never {@literal null}. */ @SuppressWarnings("unchecked") public static Collection getConvertersToRegister() { @@ -817,8 +817,8 @@ static List toList(Point point) { /** * Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPoint}s. * - * @param listOfCoordinatePairs - * @return + * @param listOfCoordinatePairs must not be {@literal null}. + * @return never {@literal null}. * @since 1.7 */ @SuppressWarnings("unchecked") @@ -841,8 +841,8 @@ static List toListOfPoint(List listOfCoordinatePairs) { /** * Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPolygon}. * - * @param dbList - * @return + * @param dbList must not be {@literal null}. + * @return never {@literal null}. * @since 1.7 */ static GeoJsonPolygon toGeoJsonPolygon(List dbList) { 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 3ca5e2156c..24ac181711 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 @@ -497,7 +497,7 @@ public DBRef toDBRef(Object object, @Nullable MongoPersistentProperty referringP * Root entry method into write conversion. Adds a type discriminator to the {@link Document}. Shouldn't be called for * nested conversions. * - * @see org.springframework.data.mongodb.core.convert.MongoWriter#write(java.lang.Object, com.mongodb.Document) + * @see org.springframework.data.mongodb.core.convert.MongoWriter#write(java.lang.Object, java.lang.Object) */ public void write(Object obj, Bson bson) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index 9269e09b8d..c5e447c9cc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -119,8 +119,8 @@ default T mapValueToTargetType(S source, Class targetType, DbRefResolv /** * Converts the given raw id value into either {@link ObjectId} or {@link String}. * - * @param id - * @param targetType + * @param id can be {@literal null}. + * @param targetType must not be {@literal null}. * @return {@literal null} if source {@literal id} is already {@literal null}. * @since 2.2 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index ec18d07677..884446cf81 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -816,7 +816,7 @@ protected static class Field { protected final String name; /** - * Creates a new {@link DocumentField} without meta-information but the given name. + * Creates a new {@link Field} without meta-information but the given name. * * @param name must not be {@literal null} or empty. */ @@ -827,7 +827,7 @@ public Field(String name) { } /** - * Returns a new {@link DocumentField} with the given name. + * Returns a new {@link Field} with the given name. * * @param name must not be {@literal null} or empty. * @return diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java index f18593c3ba..0fa9429e4c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java @@ -37,7 +37,7 @@ interface ValueResolver { * @param prop * @param bson * @param evaluator - * @param parent + * @param path * @return */ @Nullable diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java index 8e1a3c9233..5c07fb8d1b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.core.geo; /** - * Interface definition for structures defined in GeoJSON ({@link https://geojson.org/}) format. + * Interface definition for structures defined in https://docs.mongodb.org/manual/core/index-unique/ */ @@ -97,14 +97,14 @@ /** * If set to true index will skip over any document that is missing the indexed field. * - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/index-sparse/ */ boolean sparse() default false; /** - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping * @deprecated since 2.1. No longer supported by MongoDB as of server version 3.0. @@ -148,7 +148,7 @@ * db.hybrid.createIndex( { h1: 1, h2: 1 } , { name: "compound_index" } ) * * - * @return + * @return empty String by default. */ String name() default ""; @@ -156,7 +156,7 @@ * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults * to {@literal false}. * - * @return + * @return {@literal false} by default * @since 1.5 */ boolean useGeneratedName() default false; @@ -164,7 +164,7 @@ /** * If {@literal true} the index will be created in the background. * - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/indexes/#background-construction */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java index e0f7d4da98..9da7562406 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java @@ -72,7 +72,7 @@ * * * - * @return + * @return empty {@link String} by default. */ String name() default ""; @@ -80,7 +80,7 @@ * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults * to {@literal false}. * - * @return + * @return {@literal false} by default. * @since 1.5 */ boolean useGeneratedName() default false; @@ -88,21 +88,21 @@ /** * Minimum value for indexed values. * - * @return + * @return {@literal -180} by default. */ int min() default -180; /** * Maximum value for indexed values. * - * @return + * @return {@literal +180} by default. */ int max() default 180; /** * Bits of precision for boundary calculations. * - * @return + * @return {@literal 26} by default. */ int bits() default 26; @@ -110,7 +110,7 @@ * The type of the geospatial index. Default is {@link GeoSpatialIndexType#GEO_2D} * * @since 1.4 - * @return + * @return {@link GeoSpatialIndexType#GEO_2D} by default. */ GeoSpatialIndexType type() default GeoSpatialIndexType.GEO_2D; @@ -118,7 +118,7 @@ * The bucket size for {@link GeoSpatialIndexType#GEO_HAYSTACK} indexes, in coordinate units. * * @since 1.4 - * @return + * @return {@literal 1.0} by default. */ double bucketSize() default 1.0; @@ -126,7 +126,7 @@ * The name of the additional field to use for {@link GeoSpatialIndexType#GEO_HAYSTACK} indexes * * @since 1.4 - * @return + * @return empty {@link String} by default. */ String additionalField() default ""; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java index b54067d7bb..997d962ac2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java @@ -59,7 +59,7 @@ public GeospatialIndex(String field) { /** * @param name must not be {@literal null} or empty. - * @return + * @return this. */ public GeospatialIndex named(String name) { @@ -69,7 +69,7 @@ public GeospatialIndex named(String name) { /** * @param min - * @return + * @return this. */ public GeospatialIndex withMin(int min) { this.min = Integer.valueOf(min); @@ -78,7 +78,7 @@ public GeospatialIndex withMin(int min) { /** * @param max - * @return + * @return this. */ public GeospatialIndex withMax(int max) { this.max = Integer.valueOf(max); @@ -87,7 +87,7 @@ public GeospatialIndex withMax(int max) { /** * @param bits - * @return + * @return this. */ public GeospatialIndex withBits(int bits) { this.bits = Integer.valueOf(bits); @@ -96,7 +96,7 @@ public GeospatialIndex withBits(int bits) { /** * @param type must not be {@literal null}. - * @return + * @return this. */ public GeospatialIndex typed(GeoSpatialIndexType type) { @@ -108,7 +108,7 @@ public GeospatialIndex typed(GeoSpatialIndexType type) { /** * @param bucketSize - * @return + * @return this. */ public GeospatialIndex withBucketSize(double bucketSize) { this.bucketSize = bucketSize; @@ -116,8 +116,8 @@ public GeospatialIndex withBucketSize(double bucketSize) { } /** - * @param fieldName. - * @return + * @param fieldName + * @return this. */ public GeospatialIndex withAdditionalField(String fieldName) { this.additionalField = fieldName; @@ -128,7 +128,7 @@ public GeospatialIndex withAdditionalField(String fieldName) { * Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}. * * @param filter can be {@literal null}. - * @return + * @return this. * @see https://docs.mongodb.com/manual/core/index-partial/ * @since 1.10 @@ -146,7 +146,7 @@ public GeospatialIndex partial(@Nullable IndexFilter filter) { * index. * * @param collation can be {@literal null}. - * @return + * @return this. * @since 2.0 */ public GeospatialIndex collation(@Nullable Collation collation) { @@ -155,6 +155,11 @@ public GeospatialIndex collation(@Nullable Collation collation) { return this; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexKeys() + */ + @Override public Document getIndexKeys() { Document document = new Document(); @@ -184,6 +189,11 @@ public Document getIndexKeys() { return document; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexOptions() + */ + @Override public Document getIndexOptions() { Document document = new Document(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java index 40bb8f0788..4fe5093d6a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java @@ -40,7 +40,7 @@ private HashedIndex(String field) { * Creates a new {@link HashedIndex} for the given field. * * @param field must not be {@literal null} nor empty. - * @return + * @return new instance of {@link HashedIndex}. */ public static HashedIndex hashed(String field) { return new HashedIndex(field); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java index 3637909214..6a7807ef31 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java @@ -73,7 +73,7 @@ public Index named(String name) { /** * Reject all documents that contain a duplicate value for the indexed field. * - * @return + * @return this. * @see https://docs.mongodb.org/manual/core/index-unique/ */ @@ -85,7 +85,7 @@ public Index unique() { /** * Skip over any document that is missing the indexed field. * - * @return + * @return this. * @see https://docs.mongodb.org/manual/core/index-sparse/ */ @@ -97,7 +97,7 @@ public Index sparse() { /** * Build the index in background (non blocking). * - * @return + * @return this. * @since 1.5 */ public Index background() { @@ -110,7 +110,7 @@ public Index background() { * Specifies TTL in seconds. * * @param value - * @return + * @return this. * @since 1.5 */ public Index expire(long value) { @@ -135,8 +135,8 @@ public Index expire(Duration timeout) { * Specifies TTL with given {@link TimeUnit}. * * @param value - * @param unit - * @return + * @param unit must not be {@literal null}. + * @return this. * @since 1.5 */ public Index expire(long value, TimeUnit unit) { @@ -150,7 +150,7 @@ public Index expire(long value, TimeUnit unit) { * Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}. * * @param filter can be {@literal null}. - * @return + * @return this. * @see https://docs.mongodb.com/manual/core/index-partial/ * @since 1.10 @@ -168,7 +168,7 @@ public Index partial(@Nullable IndexFilter filter) { * index. * * @param collation can be {@literal null}. - * @return + * @return this. * @since 2.0 */ public Index collation(@Nullable Collation collation) { @@ -192,6 +192,10 @@ public Document getIndexKeys() { return document; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexOptions() + */ public Document getIndexOptions() { Document document = new Document(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java index 2bc2c99ffa..0051954a8d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java @@ -24,7 +24,17 @@ */ public interface IndexDefinition { + /** + * Get the {@link Document} containing properties covered by the index. + * + * @return never {@literal null}. + */ Document getIndexKeys(); + /** + * Get the index properties such as {@literal unique},... + * + * @return never {@literal null}. + */ Document getIndexOptions(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java index dc5d5d60ac..57a7912f10 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java @@ -81,7 +81,7 @@ static IndexField hashed(String key) { * Creates a geo {@link IndexField} for the given key. * * @param key must not be {@literal null} or empty. - * @return + * @return new instance of {@link IndexField}. */ public static IndexField geo(String key) { return new IndexField(key, null, Type.GEO); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java index 02ff07d658..77689cfccb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java @@ -29,7 +29,7 @@ public interface IndexFilter { /** * Get the raw (unmapped) filter expression. * - * @return + * @return never {@literal null}. */ Document getFilterObject(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java index d3c923c42f..99bbb2089b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java @@ -68,8 +68,8 @@ public IndexInfo(List indexFields, String name, boolean unique, bool /** * Creates new {@link IndexInfo} parsing required properties from the given {@literal sourceDocument}. * - * @param sourceDocument - * @return + * @param sourceDocument never {@literal null}. + * @return new instance of {@link IndexInfo}. * @since 1.10 */ public static IndexInfo indexInfoOf(Document sourceDocument) { @@ -135,7 +135,7 @@ public static IndexInfo indexInfoOf(Document sourceDocument) { } /** - * @param sourceDocument + * @param sourceDocument never {@literal null}. * @return the {@link String} representation of the partial filter {@link Document}. * @since 2.1.11 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java index c948898d00..4200535cd0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java @@ -52,7 +52,7 @@ static IndexResolver create( * Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s * are created for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}. * - * @param typeInformation + * @param typeInformation must not be {@literal null}. * @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type. */ Iterable resolveIndexFor(TypeInformation typeInformation); @@ -61,7 +61,7 @@ static IndexResolver create( * Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s * are created for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}. * - * @param entityType + * @param entityType must not be {@literal null}. * @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type. * @see 2.2 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java index e4fb9452cb..ebaa3a96e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java @@ -39,25 +39,30 @@ /** * If set to true reject all documents that contain a duplicate value for the indexed field. * - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/index-unique/ */ boolean unique() default false; + /** + * The index sort direction. + * + * @return {@link IndexDirection#ASCENDING} by default. + */ IndexDirection direction() default IndexDirection.ASCENDING; /** * If set to true index will skip over any document that is missing the indexed field. * - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/index-sparse/ */ boolean sparse() default false; /** - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping * @deprecated since 2.1. No longer supported by MongoDB as of server version 3.0. @@ -105,7 +110,7 @@ * * * - * @return + * @return empty String by default. */ String name() default ""; @@ -113,7 +118,7 @@ * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults * to {@literal false}. * - * @return + * @return {@literal false} by default. * @since 1.5 */ boolean useGeneratedName() default false; @@ -121,7 +126,7 @@ /** * If {@literal true} the index will be created in the background. * - * @return + * @return {@literal false} by default. * @see https://docs.mongodb.org/manual/core/indexes/#background-construction */ @@ -130,7 +135,7 @@ /** * Configures the number of seconds after which the collection should expire. Defaults to -1 for no expiry. * - * @return + * @return {@literal -1} by default. * @see https://docs.mongodb.org/manual/tutorial/expire-data/ */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java index 172c10590f..6c37cfedda 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java @@ -77,7 +77,7 @@ public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, * {@link MongoDatabaseFactory}. * * @param mappingContext must not be {@literal null}. - * @param mongoDbFactory must not be {@literal null}. + * @param indexOperationsProvider must not be {@literal null}. * @param indexResolver must not be {@literal null}. */ public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index 3a9fa8a668..e0a1c4d399 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -261,7 +261,7 @@ public int compare(@Nullable MongoPersistentProperty o1, @Nullable MongoPersiste * ambiguity a @see {@link MappingException} is thrown. * * @param property - the new id property candidate - * @return + * @return can be {@literal null}. */ @Override protected MongoPersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNull(MongoPersistentProperty property) { @@ -313,7 +313,7 @@ protected MongoPersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNul * {@link LiteralExpression} (indicating that no subsequent evaluation is necessary). * * @param potentialExpression can be {@literal null} - * @return + * @return can be {@literal null}. */ @Nullable private static Expression detectExpression(@Nullable String potentialExpression) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index f0caf4e7d5..e4de736c54 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -67,10 +67,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope /** * Creates a new {@link BasicMongoPersistentProperty}. * - * @param property - * @param owner - * @param simpleTypeHolder - * @param fieldNamingStrategy + * @param property the source property. + * @param owner the owing entity. + * @param simpleTypeHolder must not be {@literal null}. + * @param fieldNamingStrategy can be {@literal null}. */ public BasicMongoPersistentProperty(Property property, MongoPersistentEntity owner, SimpleTypeHolder simpleTypeHolder, @Nullable FieldNamingStrategy fieldNamingStrategy) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java index ddda7e8892..d0c1aad819 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java @@ -40,13 +40,13 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty /** * Creates a new {@link CachingMongoPersistentProperty}. * - * @param property - * @param owner - * @param simpleTypeHolder - * @param fieldNamingStrategy + * @param property must not be {@literal null}. + * @param owner must not be {@literal null}. + * @param simpleTypeHolder must not be {@literal null}. + * @param fieldNamingStrategy can be {@literal null}. */ public CachingMongoPersistentProperty(Property property, MongoPersistentEntity owner, - SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) { + SimpleTypeHolder simpleTypeHolder, @Nullable FieldNamingStrategy fieldNamingStrategy) { super(property, owner, simpleTypeHolder, fieldNamingStrategy); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java index 3bbbb3d7fe..b7d524be86 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java @@ -39,14 +39,14 @@ /** * The database the referred entity resides in. * - * @return + * @return empty String by default. */ String db() default ""; /** * Controls whether the referenced entity should be loaded lazily. This defaults to {@literal false}. * - * @return + * @return {@literal false} by default. */ boolean lazy() default false; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java index e806477e4e..c1ffd8c6c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java @@ -60,7 +60,7 @@ /** * Defines the default language to be used with this document. * - * @return + * @return an empty String by default. * @since 1.6 */ String language() default ""; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java index b5a3afc41c..15c470538f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java @@ -70,7 +70,7 @@ public interface MongoPersistentEntity extends PersistentEntity type, String co /** * Returns the type for which the {@link AbstractDeleteEvent} shall be invoked for. * - * @return + * @return can be {@literal null}. */ @Nullable public Class getType() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java index 29a1b58552..27192183af 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java @@ -33,7 +33,7 @@ public class AfterDeleteEvent extends AbstractDeleteEvent { /** * Creates a new {@link AfterDeleteEvent} for the given {@link Document}, type and collectionName. * - * @param dbo must not be {@literal null}. + * @param document must not be {@literal null}. * @param type may be {@literal null}. * @param collectionName must not be {@literal null}. * @since 1.8 diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java index 1f9c07766f..42c6da2d49 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java @@ -51,7 +51,7 @@ public AfterLoadEvent(Document document, Class type, String collectionName) { /** * Returns the type for which the {@link AfterLoadEvent} shall be invoked for. * - * @return + * @return never {@literal null}. */ public Class getType() { return type; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java index 3aee394e8a..ed80383294 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java @@ -28,7 +28,7 @@ public interface Cancelable { /** * Abort and free resources. * - * @throws DataAccessResourceFailureException + * @throws DataAccessResourceFailureException if operation cannot be canceled. */ void cancel() throws DataAccessResourceFailureException; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java index f3fa017943..4056367525 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java @@ -268,7 +268,7 @@ private static boolean isValidCursor(@Nullable MongoCursor cursor) { * exception. * * @param callback must not be {@literal null}. - * @param + * @param * @return can be {@literal null}. * @throws RuntimeException The potentially translated exception. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java index 510aac2760..13b27f9007 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java @@ -77,7 +77,7 @@ class MessageProperties { /** * The database name the message originates from. * - * @return + * @return can be {@literal null}. */ @Nullable public String getDatabaseName() { @@ -87,7 +87,7 @@ public String getDatabaseName() { /** * The collection name the message originates from. * - * @return + * @return can be {@literal null}. */ @Nullable public String getCollectionName() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java index 6fdb0496d5..9a43376dc9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java @@ -94,7 +94,7 @@ default Subscription register(SubscriptionRequest Subscription register(SubscriptionRequest request, Class bodyType); @@ -127,7 +127,7 @@ default Subscription register(SubscriptionRequestMongoDB Reference - * Collation Document */ @@ -181,7 +181,7 @@ public static Collation from(Document source) { /** * Set the level of comparison to perform. * - * @param strength + * @param strength comparison level. * @return new {@link Collation}. */ public Collation strength(int strength) { @@ -206,7 +206,7 @@ public Collation strength(ComparisonLevel comparisonLevel) { /** * Set whether to include {@code caseLevel} comparison.
      * - * @param caseLevel + * @param caseLevel use {@literal true} to enable {@code caseLevel} comparison. * @return new {@link Collation}. */ public Collation caseLevel(boolean caseLevel) { @@ -220,7 +220,7 @@ public Collation caseLevel(boolean caseLevel) { * Set the flag that determines sort order of case differences during tertiary level comparisons. * * @param caseFirst must not be {@literal null}. - * @return + * @return new instance of {@link Collation}. */ public Collation caseFirst(String caseFirst) { return caseFirst(new CaseFirst(caseFirst)); @@ -229,8 +229,8 @@ public Collation caseFirst(String caseFirst) { /** * Set the flag that determines sort order of case differences during tertiary level comparisons. * - * @param caseFirst must not be {@literal null}. - * @return + * @param sort must not be {@literal null}. + * @return new instance of {@link Collation}. */ public Collation caseFirst(CaseFirst sort) { @@ -372,7 +372,7 @@ public Collation maxVariable(String maxVariable) { /** * Get the {@link Document} representation of the {@link Collation}. * - * @return + * @return the native MongoDB {@link Document} representation of the {@link Collation}. */ public Document toDocument() { return map(toMongoDocumentConverter()); @@ -381,7 +381,7 @@ public Document toDocument() { /** * Get the {@link com.mongodb.client.model.Collation} representation of the {@link Collation}. * - * @return + * @return he native MongoDB representation of the {@link Collation}. */ public com.mongodb.client.model.Collation toMongoCollation() { return map(toMongoCollationConverter()); @@ -390,9 +390,9 @@ public com.mongodb.client.model.Collation toMongoCollation() { /** * Transform {@code this} {@link Collation} by applying a {@link Converter}. * - * @param mapper + * @param mapper must not be {@literal null}. * @param - * @return + * @return the converted result. */ public R map(Converter mapper) { return mapper.convert(this); @@ -771,7 +771,7 @@ public static class CollationLocale { * Create new {@link CollationLocale} for given language. * * @param language must not be {@literal null}. - * @return + * @return new instance of {@link CollationLocale}. */ public static CollationLocale of(String language) { @@ -794,7 +794,7 @@ public CollationLocale variant(String variant) { /** * Get the string representation. * - * @return + * @return the collation {@link String} in Mongo ICU format. */ public String asString() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 99dcb21e15..364af00935 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -29,7 +29,6 @@ import org.bson.BsonRegularExpression; import org.bson.Document; import org.bson.types.Binary; - import org.springframework.data.domain.Example; import org.springframework.data.geo.Circle; import org.springframework.data.geo.Point; @@ -105,8 +104,8 @@ protected Criteria(List criteriaChain, String key) { /** * Static factory method to create a Criteria using the provided key * - * @param key - * @return + * @param key the property or field name. + * @return new instance of {@link Criteria}. */ public static Criteria where(String key) { return new Criteria(key); @@ -116,7 +115,7 @@ public static Criteria where(String key) { * Static factory method to create a {@link Criteria} matching an example object. * * @param example must not be {@literal null}. - * @return + * @return new instance of {@link Criteria}. * @see Criteria#alike(Example) * @since 1.8 */ @@ -128,7 +127,7 @@ public static Criteria byExample(Object example) { * Static factory method to create a {@link Criteria} matching an example object. * * @param example must not be {@literal null}. - * @return + * @return new instance of {@link Criteria}. * @see Criteria#alike(Example) * @since 1.8 */ @@ -153,7 +152,7 @@ public static Criteria matchingDocumentStructure(MongoJsonSchema schema) { /** * Static factory method to create a Criteria using the provided key * - * @return + * @return new instance of {@link Criteria}. */ public Criteria and(String key) { return new Criteria(this.criteriaChain, key); @@ -162,10 +161,10 @@ public Criteria and(String key) { /** * Creates a criterion using equality * - * @param o - * @return + * @param value can be {@literal null}. + * @return this. */ - public Criteria is(@Nullable Object o) { + public Criteria is(@Nullable Object value) { if (!isValue.equals(NOT_SET)) { throw new InvalidMongoDbApiUsageException( @@ -176,7 +175,7 @@ public Criteria is(@Nullable Object o) { throw new InvalidMongoDbApiUsageException("Invalid query: 'not' can't be used with 'is' - use 'ne' instead."); } - this.isValue = o; + this.isValue = value; return this; } @@ -187,120 +186,120 @@ private boolean lastOperatorWasNot() { /** * Creates a criterion using the {@literal $ne} operator. * - * @param o - * @return + * @param value can be {@literal null}. + * @return this. * @see MongoDB Query operator: $ne */ - public Criteria ne(@Nullable Object o) { - criteria.put("$ne", o); + public Criteria ne(@Nullable Object value) { + criteria.put("$ne", value); return this; } /** * Creates a criterion using the {@literal $lt} operator. * - * @param o - * @return + * @param value must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $lt */ - public Criteria lt(Object o) { - criteria.put("$lt", o); + public Criteria lt(Object value) { + criteria.put("$lt", value); return this; } /** * Creates a criterion using the {@literal $lte} operator. * - * @param o - * @return + * @param value must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $lte */ - public Criteria lte(Object o) { - criteria.put("$lte", o); + public Criteria lte(Object value) { + criteria.put("$lte", value); return this; } /** * Creates a criterion using the {@literal $gt} operator. * - * @param o - * @return + * @param value must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $gt */ - public Criteria gt(Object o) { - criteria.put("$gt", o); + public Criteria gt(Object value) { + criteria.put("$gt", value); return this; } /** * Creates a criterion using the {@literal $gte} operator. * - * @param o - * @return + * @param value can be {@literal null}. + * @return this. * @see MongoDB Query operator: $gte */ - public Criteria gte(Object o) { - criteria.put("$gte", o); + public Criteria gte(Object value) { + criteria.put("$gte", value); return this; } /** * Creates a criterion using the {@literal $in} operator. * - * @param o the values to match against - * @return + * @param values the values to match against + * @return this. * @see MongoDB Query operator: $in */ - public Criteria in(Object... o) { - if (o.length > 1 && o[1] instanceof Collection) { + public Criteria in(Object... values) { + if (values.length > 1 && values[1] instanceof Collection) { throw new InvalidMongoDbApiUsageException( - "You can only pass in one argument of type " + o[1].getClass().getName()); + "You can only pass in one argument of type " + values[1].getClass().getName()); } - criteria.put("$in", Arrays.asList(o)); + criteria.put("$in", Arrays.asList(values)); return this; } /** * Creates a criterion using the {@literal $in} operator. * - * @param c the collection containing the values to match against - * @return + * @param values the collection containing the values to match against + * @return this. * @see MongoDB Query operator: $in */ - public Criteria in(Collection c) { - criteria.put("$in", c); + public Criteria in(Collection values) { + criteria.put("$in", values); return this; } /** * Creates a criterion using the {@literal $nin} operator. * - * @param o - * @return + * @param values + * @return this. * @see MongoDB Query operator: $nin */ - public Criteria nin(Object... o) { - return nin(Arrays.asList(o)); + public Criteria nin(Object... values) { + return nin(Arrays.asList(values)); } /** * Creates a criterion using the {@literal $nin} operator. * - * @param o - * @return + * @param values must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $nin */ - public Criteria nin(Collection o) { - criteria.put("$nin", o); + public Criteria nin(Collection values) { + criteria.put("$nin", values); return this; } /** * Creates a criterion using the {@literal $mod} operator. * - * @param value - * @param remainder - * @return + * @param value must not be {@literal null}. + * @param remainder must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $mod */ public Criteria mod(Number value, Number remainder) { @@ -314,59 +313,59 @@ public Criteria mod(Number value, Number remainder) { /** * Creates a criterion using the {@literal $all} operator. * - * @param o - * @return + * @param values must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $all */ - public Criteria all(Object... o) { - return all(Arrays.asList(o)); + public Criteria all(Object... values) { + return all(Arrays.asList(values)); } /** * Creates a criterion using the {@literal $all} operator. * - * @param o - * @return + * @param values must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $all */ - public Criteria all(Collection o) { - criteria.put("$all", o); + public Criteria all(Collection values) { + criteria.put("$all", values); return this; } /** * Creates a criterion using the {@literal $size} operator. * - * @param s - * @return + * @param size + * @return this. * @see MongoDB Query operator: $size */ - public Criteria size(int s) { - criteria.put("$size", s); + public Criteria size(int size) { + criteria.put("$size", size); return this; } /** * Creates a criterion using the {@literal $exists} operator. * - * @param b - * @return + * @param value + * @return this. * @see MongoDB Query operator: $exists */ - public Criteria exists(boolean b) { - criteria.put("$exists", b); + public Criteria exists(boolean value) { + criteria.put("$exists", value); return this; } /** * Creates a criterion using the {@literal $type} operator. * - * @param t - * @return + * @param typeNumber + * @return this. * @see MongoDB Query operator: $type */ - public Criteria type(int t) { - criteria.put("$type", t); + public Criteria type(int typeNumber) { + criteria.put("$type", typeNumber); return this; } @@ -374,7 +373,7 @@ public Criteria type(int t) { * Creates a criterion using the {@literal $type} operator. * * @param types must not be {@literal null}. - * @return this + * @return this. * @since 2.1 * @see MongoDB Query operator: $type */ @@ -390,7 +389,7 @@ public Criteria type(Type... types) { /** * Creates a criterion using the {@literal $not} meta operator which affects the clause directly following * - * @return + * @return this. * @see MongoDB Query operator: $not */ public Criteria not() { @@ -400,8 +399,8 @@ public Criteria not() { /** * Creates a criterion using the {@literal $not} operator. * - * @param value - * @return + * @param value can be {@literal null}. + * @return this. * @see MongoDB Query operator: $not */ private Criteria not(@Nullable Object value) { @@ -412,31 +411,31 @@ private Criteria not(@Nullable Object value) { /** * Creates a criterion using a {@literal $regex} operator. * - * @param re - * @return + * @param regex must not be {@literal null}. + * @return this. * @see MongoDB Query operator: $regex */ - public Criteria regex(String re) { - return regex(re, null); + public Criteria regex(String regex) { + return regex(regex, null); } /** * Creates a criterion using a {@literal $regex} and {@literal $options} operator. * - * @param re - * @param options - * @return + * @param regex must not be {@literal null}. + * @param options can be {@literal null}. + * @return this. * @see MongoDB Query operator: $regex */ - public Criteria regex(String re, @Nullable String options) { - return regex(toPattern(re, options)); + public Criteria regex(String regex, @Nullable String options) { + return regex(toPattern(regex, options)); } /** * Syntactical sugar for {@link #is(Object)} making obvious that we create a regex predicate. * - * @param pattern - * @return + * @param pattern must not be {@literal null}. + * @return this. */ public Criteria regex(Pattern pattern) { @@ -450,6 +449,12 @@ public Criteria regex(Pattern pattern) { return this; } + /** + * Use a MongoDB native {@link BsonRegularExpression}. + * + * @param regex must not be {@literal null}. + * @return this. + */ public Criteria regex(BsonRegularExpression regex) { if (lastOperatorWasNot()) { @@ -472,7 +477,7 @@ private Pattern toPattern(String regex, @Nullable String options) { * Mongo 2.4 and higher. * * @param circle must not be {@literal null} - * @return + * @return this. * @see MongoDB Query operator: * $geoWithin * @see MongoDB Query operator: @@ -489,8 +494,8 @@ public Criteria withinSphere(Circle circle) { /** * Creates a geospatial criterion using a {@literal $geoWithin} operation. * - * @param shape - * @return + * @param shape must not be {@literal null}. + * @return this. * @see MongoDB Query operator: * $geoWithin */ @@ -506,7 +511,7 @@ public Criteria within(Shape shape) { * Creates a geospatial criterion using a {@literal $near} operation. * * @param point must not be {@literal null} - * @return + * @return this. * @see MongoDB Query operator: $near */ public Criteria near(Point point) { @@ -522,7 +527,7 @@ public Criteria near(Point point) { * higher. * * @param point must not be {@literal null} - * @return + * @return this. * @see MongoDB Query operator: * $nearSphere */ @@ -539,7 +544,7 @@ public Criteria nearSphere(Point point) { * structure and the documents one. Requires MongoDB 2.4 or better. * * @param geoJson must not be {@literal null}. - * @return + * @return this. * @since 1.8 */ @SuppressWarnings("rawtypes") @@ -554,7 +559,7 @@ public Criteria intersects(GeoJson geoJson) { * Creates a geo-spatial criterion using a {@literal $maxDistance} operation, for use with $near * * @param maxDistance - * @return + * @return this. * @see MongoDB Query operator: * $maxDistance */ @@ -574,7 +579,7 @@ public Criteria maxDistance(double maxDistance) { * {@literal $nearSphere}. * * @param minDistance - * @return + * @return this. * @since 1.7 */ public Criteria minDistance(double minDistance) { @@ -591,21 +596,21 @@ public Criteria minDistance(double minDistance) { /** * Creates a criterion using the {@literal $elemMatch} operator * - * @param c - * @return + * @param criteria must not be {@literal null}. + * @return this. * @see MongoDB Query operator: * $elemMatch */ - public Criteria elemMatch(Criteria c) { - criteria.put("$elemMatch", c.getCriteriaObject()); + public Criteria elemMatch(Criteria criteria) { + this.criteria.put("$elemMatch", criteria.getCriteriaObject()); return this; } /** * Creates a criterion using the given object as a pattern. * - * @param sample - * @return + * @param sample must not be {@literal null}. + * @return this. * @since 1.8 */ public Criteria alike(Example sample) { @@ -657,7 +662,8 @@ public BitwiseCriteriaOperators bits() { *

      * * @throws IllegalArgumentException if {@link #orOperator(Criteria...)} follows a not() call directly. - * @param criteria + * @param criteria must not be {@literal null}. + * @return this. */ public Criteria orOperator(Criteria... criteria) { BasicDBList bsonList = createCriteriaList(criteria); @@ -671,7 +677,8 @@ public Criteria orOperator(Criteria... criteria) { *

      * * @throws IllegalArgumentException if {@link #norOperator(Criteria...)} follows a not() call directly. - * @param criteria + * @param criteria must not be {@literal null}. + * @return this. */ public Criteria norOperator(Criteria... criteria) { BasicDBList bsonList = createCriteriaList(criteria); @@ -685,7 +692,8 @@ public Criteria norOperator(Criteria... criteria) { *

      * * @throws IllegalArgumentException if {@link #andOperator(Criteria...)} follows a not() call directly. - * @param criteria + * @param criteria must not be {@literal null}. + * @return this. */ public Criteria andOperator(Criteria... criteria) { BasicDBList bsonList = createCriteriaList(criteria); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java index b18e7831e8..5217fb756a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java @@ -67,7 +67,8 @@ public String getCommand() { * Returns the MongoDB command for the given {@link Shape}. * * @param shape must not be {@literal null}. - * @return + * @return never {@literal null}. + * @throws IllegalArgumentException for unknown {@link Shape}. */ private String getCommand(Shape shape) { 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 154d5de591..291af0c655 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 @@ -67,7 +67,7 @@ public class Query { * Static factory method to create a {@link Query} using the provided {@link CriteriaDefinition}. * * @param criteriaDefinition must not be {@literal null}. - * @return + * @return new instance of {@link Query}. * @since 1.6 */ public static Query query(CriteriaDefinition criteriaDefinition) { @@ -90,7 +90,7 @@ public Query(CriteriaDefinition criteriaDefinition) { * Adds the given {@link CriteriaDefinition} to the current {@link Query}. * * @param criteriaDefinition must not be {@literal null}. - * @return + * @return this. * @since 1.6 */ public Query addCriteria(CriteriaDefinition criteriaDefinition) { @@ -124,7 +124,7 @@ public Field fields() { * Set number of documents to skip before returning results. * * @param skip - * @return + * @return this. */ public Query skip(long skip) { this.skip = skip; @@ -135,7 +135,7 @@ public Query skip(long skip) { * Limit the number of returned documents to {@code limit}. * * @param limit - * @return + * @return this. */ public Query limit(int limit) { this.limit = limit; @@ -147,7 +147,7 @@ public Query limit(int limit) { * json {@link Document} representation. * * @param hint must not be {@literal null} or empty. - * @return + * @return this. * @see Document#parse(String) */ public Query withHint(String hint) { @@ -161,7 +161,7 @@ public Query withHint(String hint) { * Configures the query to use the given {@link Document hint} when being executed. * * @param hint must not be {@literal null}. - * @return + * @return this. * @since 2.2 */ public Query withHint(Document hint) { @@ -175,8 +175,8 @@ public Query withHint(Document hint) { * Sets the given pagination information on the {@link Query} instance. Will transparently set {@code skip} and * {@code limit} as well as applying the {@link Sort} instance defined with the {@link Pageable}. * - * @param pageable - * @return + * @param pageable must not be {@literal null}. + * @return this. */ public Query with(Pageable pageable) { @@ -193,8 +193,8 @@ public Query with(Pageable pageable) { /** * Adds a {@link Sort} to the {@link Query} instance. * - * @param sort - * @return + * @param sort must not be {@literal null}. + * @return this. */ public Query with(Sort sort) { @@ -227,7 +227,7 @@ public Set> getRestrictedTypes() { * * @param type may not be {@literal null} * @param additionalTypes may not be {@literal null} - * @return + * @return this. */ public Query restrict(Class type, Class... additionalTypes) { @@ -296,7 +296,7 @@ public boolean isSorted() { /** * Get the number of documents to skip. * - * @return + * @return number of documents to skip */ public long getSkip() { return this.skip; @@ -305,14 +305,14 @@ public long getSkip() { /** * Get the maximum number of documents to be return. * - * @return + * @return number of documents to return. */ public int getLimit() { return this.limit; } /** - * @return + * @return can be {@literal null}. */ @Nullable public String getHint() { @@ -333,7 +333,7 @@ public Query maxTimeMsec(long maxTimeMsec) { /** * @param timeout - * @param timeUnit + * @param timeUnit must not be {@literal null}. * @return this. * @see Meta#setMaxTime(long, TimeUnit) * @since 1.6 @@ -347,7 +347,7 @@ public Query maxTime(long timeout, TimeUnit timeUnit) { } /** - * @param timeout + * @param timeout must not be {@literal null}. * @return this. * @see Meta#setMaxTime(Duration) * @since 2.1 @@ -361,7 +361,7 @@ public Query maxTime(Duration timeout) { /** * Add a comment to the query that is propagated to the profile log. * - * @param comment + * @param comment must not be {@literal null}. * @return this. * @see Meta#setComment(String) * @since 1.6 @@ -456,7 +456,7 @@ public void setMeta(Meta meta) { * Set the {@link Collation} applying language-specific rules for string comparison. * * @param collation can be {@literal null}. - * @return + * @return this. * @since 2.0 */ public Query collation(@Nullable Collation collation) { @@ -468,7 +468,7 @@ public Query collation(@Nullable Collation collation) { /** * Get the {@link Collation} defining language-specific rules for string comparison. * - * @return + * @return never {@literal null}. * @since 2.0 */ public Optional getCollation() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java index 0f1e40550e..0560b5d384 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java @@ -65,8 +65,8 @@ public TextQuery(String wordsAndPhrases, @Nullable String language) { * For a full list of supported languages see the mongdodb reference manual for * Text Search Languages. * - * @param wordsAndPhrases - * @param locale + * @param wordsAndPhrases must not be {@literal null}. + * @param locale can be {@literal null}. */ public TextQuery(String wordsAndPhrases, @Nullable Locale locale) { this(wordsAndPhrases, locale != null ? locale.getLanguage() : (String) null); @@ -75,7 +75,7 @@ public TextQuery(String wordsAndPhrases, @Nullable Locale locale) { /** * Creates new {@link TextQuery} for given {@link TextCriteria}. * - * @param criteria. + * @param criteria must not be {@literal null}. */ public TextQuery(TextCriteria criteria) { super(criteria); @@ -84,8 +84,8 @@ public TextQuery(TextCriteria criteria) { /** * Creates new {@link TextQuery} searching for given {@link TextCriteria}. * - * @param criteria - * @return + * @param criteria must not be {@literal null}. + * @return new instance of {@link TextQuery}. */ public static TextQuery queryText(TextCriteria criteria) { return new TextQuery(criteria); @@ -95,7 +95,7 @@ public static TextQuery queryText(TextCriteria criteria) { * Add sorting by text score. Will also add text score to returned fields. * * @see TextQuery#includeScore() - * @return + * @return this. */ public TextQuery sortByScore() { @@ -107,7 +107,7 @@ public TextQuery sortByScore() { /** * Add field {@literal score} holding the documents textScore to the returned fields. * - * @return + * @return this. */ public TextQuery includeScore() { @@ -118,8 +118,8 @@ public TextQuery includeScore() { /** * Include text search document score in returned fields using the given fieldname. * - * @param fieldname - * @return + * @param fieldname must not be {@literal null}. + * @return this. */ public TextQuery includeScore(String fieldname) { @@ -131,7 +131,7 @@ public TextQuery includeScore(String fieldname) { /** * Set the fieldname used for scoring. * - * @param fieldName + * @param fieldName must not be {@literal null}. */ public void setScoreFieldName(String fieldName) { this.scoreFieldName = fieldName; @@ -140,7 +140,7 @@ public void setScoreFieldName(String fieldName) { /** * Get the fieldname used for scoring * - * @return + * @return never {@literal null}. */ public String getScoreFieldName() { return scoreFieldName; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index edb79588d8..cf2d14efd7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -64,8 +64,8 @@ public enum Position { /** * Static factory method to create an Update using the provided key * - * @param key - * @return + * @param key the field to update. + * @return new instance of {@link Update}. */ public static Update update(String key, @Nullable Object value) { return new Update().set(key, value); @@ -80,7 +80,7 @@ public static Update update(String key, @Nullable Object value) { * * @param object the source {@link Document} to create the update from. * @param exclude the fields to exclude. - * @return + * @return new instance of {@link Update}. */ public static Update fromDocument(Document object, String... exclude) { @@ -108,7 +108,7 @@ public static Update fromDocument(Document object, String... exclude) { /** * Update using the {@literal $set} update modifier * - * @param key + * @param key the field name. * @param value can be {@literal null}. In this case the property remains in the db with a {@literal null} value. To * remove it use {@link #unset(String)}. * @return this. @@ -122,9 +122,9 @@ public Update set(String key, @Nullable Object value) { /** * Update using the {@literal $setOnInsert} update modifier * - * @param key + * @param key the field name. * @param value can be {@literal null}. - * @return + * @return this. * @see MongoDB Update operator: * $setOnInsert */ @@ -136,8 +136,8 @@ public Update setOnInsert(String key, @Nullable Object value) { /** * Update using the {@literal $unset} update modifier * - * @param key - * @return + * @param key the field name. + * @return this. * @see MongoDB Update operator: $unset */ public Update unset(String key) { @@ -148,9 +148,9 @@ public Update unset(String key) { /** * Update using the {@literal $inc} update modifier * - * @param key - * @param inc - * @return + * @param key the field name. + * @param inc must not be {@literal null}. + * @return this. * @see MongoDB Update operator: $inc */ public Update inc(String key, Number inc) { @@ -170,9 +170,9 @@ public void inc(String key) { /** * Update using the {@literal $push} update modifier * - * @param key - * @param value - * @return + * @param key the field name. + * @param value can be {@literal null}. + * @return this. * @see MongoDB Update operator: $push */ public Update push(String key, @Nullable Object value) { @@ -185,7 +185,7 @@ public Update push(String key, @Nullable Object value) { * Allows creation of {@code $push} command for single or multiple (using {@code $each}) values as well as using * {@code $position}. * - * @param key + * @param key the field name. * @return {@link PushOperatorBuilder} for given key * @see MongoDB Update operator: $push * @see MongoDB Update operator: $each @@ -204,9 +204,9 @@ public PushOperatorBuilder push(String key) { * Important: As of MongoDB 3.6 {@code $pushAll} is not longer supported. Use {@code $push $each} instead. * {@link #push(String)}) returns a builder that can be used to populate the {@code $each} object. * - * @param key - * @param values - * @return + * @param key the field name. + * @param values must not be {@literal null}. + * @return this. * @see MongoDB Update operator: * $pushAll * @deprecated as of MongoDB 2.4. Removed in MongoDB 3.6. Use {@link #push(String) $push $each} instead. @@ -221,8 +221,8 @@ public Update pushAll(String key, Object[] values) { * Update using {@code $addToSet} modifier.
      * Allows creation of {@code $push} command for single or multiple (using {@code $each}) values * - * @param key - * @return + * @param key the field name. + * @return new instance of {@link AddToSetBuilder}. * @since 1.5 */ public AddToSetBuilder addToSet(String key) { @@ -232,9 +232,9 @@ public AddToSetBuilder addToSet(String key) { /** * Update using the {@literal $addToSet} update modifier * - * @param key - * @param value - * @return + * @param key the field name. + * @param value can be {@literal null}. + * @return this. * @see MongoDB Update operator: * $addToSet */ @@ -246,9 +246,9 @@ public Update addToSet(String key, @Nullable Object value) { /** * Update using the {@literal $pop} update modifier * - * @param key - * @param pos - * @return + * @param key the field name. + * @param pos must not be {@literal null}. + * @return this. * @see MongoDB Update operator: $pop */ public Update pop(String key, Position pos) { @@ -259,9 +259,9 @@ public Update pop(String key, Position pos) { /** * Update using the {@literal $pull} update modifier * - * @param key - * @param value - * @return + * @param key the field name. + * @param value can be {@literal null}. + * @return this. * @see MongoDB Update operator: $pull */ public Update pull(String key, @Nullable Object value) { @@ -272,9 +272,9 @@ public Update pull(String key, @Nullable Object value) { /** * Update using the {@literal $pullAll} update modifier * - * @param key - * @param values - * @return + * @param key the field name. + * @param values must not be {@literal null}. + * @return this. * @see MongoDB Update operator: * $pullAll */ @@ -286,9 +286,9 @@ public Update pullAll(String key, Object[] values) { /** * Update using the {@literal $rename} update modifier * - * @param oldName - * @param newName - * @return + * @param oldName must not be {@literal null}. + * @param newName must not be {@literal null}. + * @return this. * @see MongoDB Update operator: * $rename */ @@ -300,8 +300,8 @@ public Update rename(String oldName, String newName) { /** * Update given key to current date using {@literal $currentDate} modifier. * - * @param key - * @return + * @param key the field name. + * @return this. * @since 1.6 * @see MongoDB Update operator: * $currentDate @@ -315,8 +315,8 @@ public Update currentDate(String key) { /** * Update given key to current date using {@literal $currentDate : { $type : "timestamp" }} modifier. * - * @param key - * @return + * @param key the field name. + * @return this. * @since 1.6 * @see MongoDB Update operator: * $currentDate @@ -332,7 +332,7 @@ public Update currentTimestamp(String key) { * * @param key must not be {@literal null}. * @param multiplier must not be {@literal null}. - * @return + * @return this. * @since 1.7 * @see MongoDB Update operator: $mul */ @@ -348,7 +348,7 @@ public Update multiply(String key, Number multiplier) { * * @param key must not be {@literal null}. * @param value must not be {@literal null}. - * @return + * @return this. * @since 1.10 * @see Comparison/Sort Order * @see MongoDB Update operator: $max @@ -365,7 +365,7 @@ public Update max(String key, Object value) { * * @param key must not be {@literal null}. * @param value must not be {@literal null}. - * @return + * @return this. * @since 1.10 * @see Comparison/Sort Order * @see MongoDB Update operator: $min @@ -380,8 +380,8 @@ public Update min(String key, Object value) { /** * The operator supports bitwise {@code and}, bitwise {@code or}, and bitwise {@code xor} operations. * - * @param key - * @return + * @param key the field name. + * @return this. * @since 1.7 */ public BitwiseOperatorBuilder bitwise(String key) { @@ -391,9 +391,9 @@ public BitwiseOperatorBuilder bitwise(String key) { /** * Prevents a write operation that affects multiple documents from yielding to other reads or writes * once the first document is written.
      - * Use with {@link org.springframework.data.mongodb.core.MongoOperations#updateMulti(Query, Update, Class)}. + * Use with {@link org.springframework.data.mongodb.core.MongoOperations#updateMulti(Query, UpdateDefinition, Class)}. * - * @return never {@literal null}. + * @return this. * @since 2.0 */ public Update isolated() { @@ -497,8 +497,8 @@ protected void addMultiFieldOperation(String operator, String key, @Nullable Obj /** * Determine if a given {@code key} will be touched on execution. * - * @param key - * @return + * @param key the field name. + * @return {@literal true} if given field is updated. */ public boolean modifies(String key) { return this.keysToUpdate.contains(key); @@ -507,8 +507,8 @@ public boolean modifies(String key) { /** * Inspects given {@code key} for '$'. * - * @param key - * @return + * @param key the field name. + * @return {@literal true} if given key is prefixed. */ private static boolean isKeyword(String key) { return StringUtils.startsWithIgnoreCase(key, "$"); @@ -1046,8 +1046,8 @@ public AddToSetBuilder(String key) { /** * Propagates {@code $each} to {@code $addToSet} * - * @param values - * @return + * @param values must not be {@literal null}. + * @return never {@literal null}. */ public Update each(Object... values) { return Update.this.addToSet(this.key, new Each(values)); @@ -1056,8 +1056,8 @@ public Update each(Object... values) { /** * Propagates {@link #value(Object)} to {@code $addToSet} * - * @param values - * @return + * @param value + * @return never {@literal null}. */ public Update value(Object value) { return Update.this.addToSet(this.key, value); @@ -1102,7 +1102,7 @@ protected BitwiseOperatorBuilder(Update reference, String key) { * Updates to the result of a bitwise and operation between the current value and the given one. * * @param value - * @return + * @return never {@literal null}. */ public Update and(long value) { @@ -1114,7 +1114,7 @@ public Update and(long value) { * Updates to the result of a bitwise or operation between the current value and the given one. * * @param value - * @return + * @return never {@literal null}. */ public Update or(long value) { @@ -1126,7 +1126,7 @@ public Update or(long value) { * Updates to the result of a bitwise xor operation between the current value and the given one. * * @param value - * @return + * @return never {@literal null}. */ public Update xor(long value) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java index ef6d0f639c..d87247f616 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java @@ -365,7 +365,6 @@ public static class ObjectJsonSchemaProperty extends IdentifiableJsonSchemaPrope /** * @param range must not be {@literal null}. * @return new instance of {@link ObjectJsonSchemaProperty}. - * @see ObjectJsonSchemaObject#propertiesCount */ public ObjectJsonSchemaProperty propertiesCount(Range range) { return new ObjectJsonSchemaProperty(identifier, jsonSchemaObjectDelegate.propertiesCount(range)); @@ -1120,16 +1119,16 @@ public EncryptedJsonSchemaProperty algorithm(String algorithm) { } /** - * @param key - * @return + * @param keyId must not be {@literal null}. + * @return new instance of {@link EncryptedJsonSchemaProperty}. */ public EncryptedJsonSchemaProperty keyId(String keyId) { return new EncryptedJsonSchemaProperty(targetProperty, algorithm, keyId, null); } /** - * @param keyId - * @return + * @param keyId must not be {@literal null}. + * @return new instance of {@link EncryptedJsonSchemaProperty}. */ public EncryptedJsonSchemaProperty keys(UUID... keyId) { return new EncryptedJsonSchemaProperty(targetProperty, algorithm, null, Arrays.asList(keyId)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java index d13752820d..3d3c2f459a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java @@ -218,8 +218,8 @@ static TimestampJsonSchemaProperty timestamp(String identifier) { /** * Obtain a builder to create a {@link JsonSchemaProperty}. * - * @param identifier - * @return + * @param identifier must not be {@literal null}. + * @return new instance of {@link JsonSchemaPropertyBuilder}. */ static JsonSchemaPropertyBuilder named(String identifier) { return new JsonSchemaPropertyBuilder(identifier); @@ -248,7 +248,7 @@ class JsonSchemaPropertyBuilder { * Configure a {@link Type} for the property. * * @param type must not be {@literal null}. - * @return + * @return new instance of {@link IdentifiableJsonSchemaProperty}. */ public IdentifiableJsonSchemaProperty ofType(Type type) { return new IdentifiableJsonSchemaProperty<>(identifier, TypedJsonSchemaObject.of(type)); @@ -269,7 +269,7 @@ public IdentifiableJsonSchemaProperty ofType(@Nullable Cl * Configure a {@link TypedJsonSchemaObject} for the property. * * @param schemaObject must not be {@literal null}. - * @return + * @return new instance of {@link IdentifiableJsonSchemaProperty}. */ public IdentifiableJsonSchemaProperty with(TypedJsonSchemaObject schemaObject) { return new IdentifiableJsonSchemaProperty<>(identifier, schemaObject); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java index b60c52cd25..ea7bf542e1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java @@ -74,7 +74,7 @@ public interface MongoJsonSchema { * Create a new {@link MongoJsonSchema} for a given root object. * * @param root must not be {@literal null}. - * @return + * @return new instance of {@link MongoJsonSchema}. */ static MongoJsonSchema of(JsonSchemaObject root) { return new DefaultMongoJsonSchema(root); @@ -84,7 +84,7 @@ static MongoJsonSchema of(JsonSchemaObject root) { * Create a new {@link MongoJsonSchema} for a given root {@link Document} containing the schema definition. * * @param document must not be {@literal null}. - * @return + * @return new instance of {@link MongoJsonSchema}. */ static MongoJsonSchema of(Document document) { return new DocumentJsonSchema(document); @@ -135,7 +135,7 @@ public MongoJsonSchemaBuilder maxProperties(int count) { } /** - * @param properties + * @param properties must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see ObjectJsonSchemaObject#required(String...) */ @@ -157,7 +157,7 @@ public MongoJsonSchemaBuilder additionalProperties(boolean additionalPropertiesA } /** - * @param schema + * @param schema must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see ObjectJsonSchemaObject#additionalProperties(ObjectJsonSchemaObject) */ @@ -168,7 +168,7 @@ public MongoJsonSchemaBuilder additionalProperties(ObjectJsonSchemaObject schema } /** - * @param properties + * @param properties must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see ObjectJsonSchemaObject#properties(JsonSchemaProperty...) */ @@ -179,7 +179,7 @@ public MongoJsonSchemaBuilder properties(JsonSchemaProperty... properties) { } /** - * @param properties + * @param properties must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see ObjectJsonSchemaObject#patternProperties(JsonSchemaProperty...) */ @@ -190,7 +190,7 @@ public MongoJsonSchemaBuilder patternProperties(JsonSchemaProperty... properties } /** - * @param property + * @param property must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see ObjectJsonSchemaObject#property(JsonSchemaProperty) */ @@ -201,7 +201,7 @@ public MongoJsonSchemaBuilder property(JsonSchemaProperty property) { } /** - * @param possibleValues + * @param possibleValues must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see ObjectJsonSchemaObject#possibleValues(Collection) */ @@ -212,7 +212,7 @@ public MongoJsonSchemaBuilder possibleValues(Set possibleValues) { } /** - * @param allOf + * @param allOf must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see UntypedJsonSchemaObject#allOf(Collection) */ @@ -223,7 +223,7 @@ public MongoJsonSchemaBuilder allOf(Set allOf) { } /** - * @param anyOf + * @param anyOf must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see UntypedJsonSchemaObject#anyOf(Collection) */ @@ -234,7 +234,7 @@ public MongoJsonSchemaBuilder anyOf(Set anyOf) { } /** - * @param oneOf + * @param oneOf must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see UntypedJsonSchemaObject#oneOf(Collection) */ @@ -245,7 +245,7 @@ public MongoJsonSchemaBuilder oneOf(Set oneOf) { } /** - * @param notMatch + * @param notMatch must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see UntypedJsonSchemaObject#notMatch(JsonSchemaObject) */ @@ -256,7 +256,7 @@ public MongoJsonSchemaBuilder notMatch(JsonSchemaObject notMatch) { } /** - * @param description + * @param description must not be {@literal null}. * @return {@code this} {@link MongoJsonSchemaBuilder}. * @see UntypedJsonSchemaObject#description(String) */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java index fe1e13ab39..a481c53c7a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java @@ -111,7 +111,6 @@ public TypedJsonSchemaObject description(String description) { /** * Auto generate the {@literal description} if not explicitly set. * - * @param description must not be {@literal null}. * @return new instance of {@link TypedJsonSchemaObject}. */ @Override @@ -167,7 +166,7 @@ public TypedJsonSchemaObject oneOf(Collection oneOf) { /** * The field value must not match the specified schemas. * - * @param oneOf must not be {@literal null}. + * @param notMatch must not be {@literal null}. * @return new instance of {@link TypedJsonSchemaObject}. */ @Override diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java index e3d05d419f..d1f695428a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java @@ -132,7 +132,7 @@ public UntypedJsonSchemaObject oneOf(Collection oneOf) { /** * The field value must not match the specified schemas. * - * @param oneOf must not be {@literal null}. + * @param notMatch must not be {@literal null}. * @return new instance of {@link TypedJsonSchemaObject}. */ public UntypedJsonSchemaObject notMatch(JsonSchemaObject notMatch) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java index 27a337ff46..712c816ef2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java @@ -29,7 +29,7 @@ public class GridFsCriteria extends Criteria { /** * Creates a new {@link GridFsCriteria} for the given key. * - * @param key + * @param key must not be {@literal null}. */ public GridFsCriteria(String key) { super(key); @@ -38,7 +38,7 @@ public GridFsCriteria(String key) { /** * Creates a {@link GridFsCriteria} for restrictions on the file's metadata. * - * @return + * @return new instance of {@link GridFsCriteria}. */ public static GridFsCriteria whereMetaData() { return new GridFsCriteria("metadata"); @@ -47,8 +47,8 @@ public static GridFsCriteria whereMetaData() { /** * Creates a {@link GridFsCriteria} for restrictions on a single file's metadata item. * - * @param metadataKey - * @return + * @param metadataKey can be {@literal null}. + * @return new instance of {@link GridFsCriteria}. */ public static GridFsCriteria whereMetaData(@Nullable String metadataKey) { @@ -59,7 +59,7 @@ public static GridFsCriteria whereMetaData(@Nullable String metadataKey) { /** * Creates a {@link GridFsCriteria} for restrictions on the file's name. * - * @return + * @return new instance of {@link GridFsCriteria}. */ public static GridFsCriteria whereFilename() { return new GridFsCriteria("filename"); @@ -68,7 +68,7 @@ public static GridFsCriteria whereFilename() { /** * Creates a {@link GridFsCriteria} for restrictions on the file's content type. * - * @return + * @return new instance of {@link GridFsCriteria}. */ public static GridFsCriteria whereContentType() { return new GridFsCriteria("metadata.".concat(GridFsResource.CONTENT_TYPE_FIELD)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index 0366668576..502d210986 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -179,7 +179,7 @@ default ObjectId store(InputStream content, @Nullable String filename, @Nullable * case no file matches. * * @param query must not be {@literal null}. - * @return + * @return can be {@literal null}. */ @Nullable com.mongodb.client.gridfs.model.GridFSFile findOne(Query query); @@ -214,7 +214,7 @@ default ObjectId store(InputStream content, @Nullable String filename, @Nullable * Returns all {@link GridFsResource}s matching the given file name pattern. * * @param filenamePattern must not be {@literal null}. - * @return + * @return an empty array if none found. * @see ResourcePatternResolver#getResources(String) */ GridFsResource[] getResources(String filenamePattern); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 45702ef248..57b8b7df80 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -75,7 +75,7 @@ public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter) * * @param dbFactory must not be {@literal null}. * @param converter must not be {@literal null}. - * @param bucket + * @param bucket can be {@literal null}. */ public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter, @Nullable String bucket) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java index c86926db77..3d2405759b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java @@ -188,7 +188,7 @@ public GridFsUploadBuilder options(Options options) { * Set the file metadata. * * @param metadata must not be {@literal null}. - * @return + * @return this. */ public GridFsUploadBuilder metadata(Document metadata) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java index 94dcac3360..e9c1b00b74 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java @@ -37,7 +37,7 @@ public abstract class AbstractMonitor { private final MongoClient mongoClient; /** - * @param mongoClient + * @param mongoClient must not be {@literal null}. * @since 2.2 */ protected AbstractMonitor(MongoClient mongoClient) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java index 7bf4b9b55f..220bcadd3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java @@ -31,7 +31,7 @@ public class AssertMetrics extends AbstractMonitor { /** - * @param mongoClient + * @param mongoClient must not be {@literal null}. * @since 2.2 */ public AssertMetrics(MongoClient mongoClient) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java index b56fdf7694..9a502cb74a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java @@ -33,7 +33,7 @@ public class BackgroundFlushingMetrics extends AbstractMonitor { /** - * @param mongoClient + * @param mongoClient must not be {@literal null}. * @since 2.2 */ public BackgroundFlushingMetrics(MongoClient mongoClient) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java index 2afec53f22..d7480a6e12 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java @@ -31,7 +31,7 @@ public class BtreeIndexCounters extends AbstractMonitor { /** - * @param mongoClient + * @param mongoClient must not be {@literal null}. * @since 2.2 */ public BtreeIndexCounters(MongoClient mongoClient) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java index a4b428e017..ae453fd1d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java @@ -31,7 +31,7 @@ public class ConnectionMetrics extends AbstractMonitor { /** - * @param mongoClient + * @param mongoClient must not be {@literal null}. * @since 2.2 */ public ConnectionMetrics(MongoClient mongoClient) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java index 23f8813998..eb2f0d6afc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java @@ -32,7 +32,7 @@ public class GlobalLockMetrics extends AbstractMonitor { /** - * @param mongoClient + * @param mongoClient must not be {@literal null}. * @since 2.2 */ public GlobalLockMetrics(MongoClient mongoClient) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java index 8c0d5c25cb..36eb77397e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java @@ -41,7 +41,7 @@ * Takes a MongoDB JSON string to define the actual query to be executed. This one will take precedence over the * method name then. Alias for {@link Query#value}. * - * @return + * @return an empty String by default. */ @AliasFor(annotation = Query.class) String value() default ""; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java index c41ee5ba93..598941b99f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java @@ -41,7 +41,7 @@ * Takes a MongoDB JSON string to define the actual query to be executed. This one will take precedence over the * method name then. Alias for {@link Query#value}. * - * @return + * @return empty {@link String} by default. */ @AliasFor(annotation = Query.class) String value() default ""; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java index 73fcabb4ad..04b3c0225f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java @@ -40,7 +40,7 @@ * Takes a MongoDB JSON string to define the actual query to be executed. This one will take precedence over the * method name then. Alias for {@link Query#value}. * - * @return + * @return empty {@link String} by default. */ @AliasFor(annotation = Query.class) String value() default ""; 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 929e3a63eb..50288a1f73 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 @@ -37,7 +37,7 @@ /** * Set the maximum time limit in milliseconds for processing operations. * - * @return + * @return {@literal -1} by default. * @since 1.10 */ long maxExecutionTimeMs() default -1; @@ -55,7 +55,7 @@ /** * Add a comment to the query. * - * @return + * @return empty {@link String} by default. */ String comment() default ""; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java index 664c5ca8bc..88f7d11f7d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java @@ -69,7 +69,7 @@ public interface MongoRepository extends PagingAndSortingRepository * * - * @return + * @return empty {@link String} by default. * @since 2.1 */ String sort() default ""; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java index dced7913c4..7b6ed5bdb9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java @@ -47,7 +47,8 @@ /** * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.: - * {@code @EnableMongoRepositories("org.my.pkg")} instead of {@code @EnableMongoRepositories(basePackages="org.my.pkg")}. + * {@code @EnableMongoRepositories("org.my.pkg")} instead of + * {@code @EnableMongoRepositories(basePackages="org.my.pkg")}. */ String[] value() default {}; @@ -80,7 +81,7 @@ * for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning * for {@code PersonRepositoryImpl}. * - * @return + * @return {@literal Impl} by default. */ String repositoryImplementationPostfix() default "Impl"; @@ -88,7 +89,7 @@ * Configures the location of where to find the Spring Data named queries properties file. Will default to * {@code META-INFO/mongo-named-queries.properties}. * - * @return + * @return empty {@link String} by default. */ String namedQueriesLocation() default ""; @@ -96,7 +97,7 @@ * Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to * {@link Key#CREATE_IF_NOT_FOUND}. * - * @return + * @return {@link Key#CREATE_IF_NOT_FOUND} by default. */ Key queryLookupStrategy() default Key.CREATE_IF_NOT_FOUND; @@ -104,14 +105,14 @@ * Returns the {@link FactoryBean} class to be used for each repository instance. Defaults to * {@link MongoRepositoryFactoryBean}. * - * @return + * @return {@link MongoRepositoryFactoryBean} by default. */ Class repositoryFactoryBeanClass() default MongoRepositoryFactoryBean.class; /** * Configure the repository base class to be used to create repository proxies for this particular configuration. * - * @return + * @return {@link DefaultRepositoryBaseClass} by default. * @since 1.8 */ Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; @@ -119,20 +120,22 @@ /** * Configures the name of the {@link MongoTemplate} bean to be used with the repositories detected. * - * @return + * @return {@literal mongoTemplate} by default. */ String mongoTemplateRef() default "mongoTemplate"; /** * Whether to automatically create indexes for query methods defined in the repository interface. * - * @return + * @return {@literal false} by default. */ boolean createIndexesForQueryMethods() default false; /** * Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the * repositories infrastructure. + * + * @return {@literal false} by default. */ boolean considerNestedRepositories() default false; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java index 5ba8dcf8e1..7b0d540211 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java @@ -84,7 +84,7 @@ * for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning * for {@code PersonRepositoryImpl}. * - * @return + * @return {@literal Impl} by default. */ String repositoryImplementationPostfix() default "Impl"; @@ -92,7 +92,7 @@ * Configures the location of where to find the Spring Data named queries properties file. Will default to * {@code META-INF/mongo-named-queries.properties}. * - * @return + * @return empty {@link String} by default. */ String namedQueriesLocation() default ""; @@ -100,7 +100,7 @@ * Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to * {@link Key#CREATE_IF_NOT_FOUND}. * - * @return + * @return {@link Key#CREATE_IF_NOT_FOUND} by default. */ Key queryLookupStrategy() default Key.CREATE_IF_NOT_FOUND; @@ -108,34 +108,36 @@ * Returns the {@link FactoryBean} class to be used for each repository instance. Defaults to * {@link MongoRepositoryFactoryBean}. * - * @return + * @return {@link ReactiveMongoRepositoryFactoryBean} by default. */ Class repositoryFactoryBeanClass() default ReactiveMongoRepositoryFactoryBean.class; /** * Configure the repository base class to be used to create repository proxies for this particular configuration. * - * @return + * @return {@link DefaultRepositoryBaseClass} by default. */ Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; /** * Configures the name of the {@link MongoTemplate} bean to be used with the repositories detected. * - * @return + * @return {@literal reactiveMongoTemplate} by default. */ String reactiveMongoTemplateRef() default "reactiveMongoTemplate"; /** * Whether to automatically create indexes for query methods defined in the repository interface. * - * @return + * @return {@literal false} by default. */ boolean createIndexesForQueryMethods() default false; /** * Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the * repositories infrastructure. + * + * @return {@literal false} by default. */ boolean considerNestedRepositories() default false; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java index 7e05ad95fd..30ce2e81ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java @@ -159,7 +159,7 @@ public Collation getCollation() { * * @param value can be {@literal null}. * @param typeInformation can be {@literal null}. - * @return + * @return can be {@literal null}. */ @Nullable private Object getConvertedValue(Object value, @Nullable TypeInformation typeInformation) { @@ -251,8 +251,8 @@ public void remove() { * array. Will return an empty {@link Collection} in case {@literal null} is given. Will wrap all other types into a * single-element collection. * - * @param source - * @return + * @param source can be {@literal null}, returns an empty {@link List} in that case. + * @return never {@literal null}. */ private static Collection asCollection(@Nullable Object source) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java index c7f4e2a23e..bb1d112099 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java @@ -47,19 +47,19 @@ class DtoInstantiatingConverter implements Converter { * * @param dtoType must not be {@literal null}. * @param context must not be {@literal null}. - * @param instantiators must not be {@literal null}. + * @param entityInstantiators must not be {@literal null}. */ public DtoInstantiatingConverter(Class dtoType, MappingContext, MongoPersistentProperty> context, - EntityInstantiators instantiator) { + EntityInstantiators entityInstantiators) { Assert.notNull(dtoType, "DTO type must not be null!"); Assert.notNull(context, "MappingContext must not be null!"); - Assert.notNull(instantiator, "EntityInstantiators must not be null!"); + Assert.notNull(entityInstantiators, "EntityInstantiators must not be null!"); this.targetType = dtoType; this.context = context; - this.instantiator = instantiator.getInstantiatorFor(context.getRequiredPersistentEntity(dtoType)); + this.instantiator = entityInstantiators.getInstantiatorFor(context.getRequiredPersistentEntity(dtoType)); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java new file mode 100644 index 0000000000..ce2f20fcc2 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020 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 + * + * https://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. + */ + +/** + * MongoDB driver-specific utility classes for Json conversion. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.mongodb.util.json; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index e332fdf235..e7027a05a0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -1297,9 +1297,9 @@ public void processDocument(org.bson.Document document) { } }, new CursorPreparer() { - public FindIterable prepare(FindIterable cursor) { - cursor.limit(1); - return cursor; + public FindIterable prepare(FindIterable iterable) { + iterable.limit(1); + return iterable; } }); From 35196e312997aeb396fa77655e474846a6ef15db Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 6 May 2020 11:20:30 +0200 Subject: [PATCH 0165/1381] DATAMONGO-2509 - Polishing. Fix typos, improve wording. Reworks documentation specific to MongoDB 3 and 4. Original pull request: #853. --- .../data/mongodb/util/json/package-info.java | 16 --- src/main/asciidoc/index.adoc | 1 - src/main/asciidoc/reference/mapping.adoc | 12 +- src/main/asciidoc/reference/mongo-3.adoc | 127 ------------------ .../reference/mongo-repositories.adoc | 14 +- src/main/asciidoc/reference/mongodb.adoc | 52 +++---- src/main/asciidoc/upgrading.adoc | 10 ++ 7 files changed, 53 insertions(+), 179 deletions(-) delete mode 100644 src/main/asciidoc/reference/mongo-3.adoc diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java index ce2f20fcc2..8a86b3522b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/package-info.java @@ -1,19 +1,3 @@ -/* - * Copyright 2020 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 - * - * https://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. - */ - /** * MongoDB driver-specific utility classes for Json conversion. */ diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 9464e7da80..3d946df92b 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -33,7 +33,6 @@ include::reference/mapping.adoc[leveloffset=+1] include::reference/sharding.adoc[leveloffset=+1] include::reference/kotlin.adoc[leveloffset=+1] include::reference/jmx.adoc[leveloffset=+1] -include::reference/mongo-3.adoc[leveloffset=+1] [[appendix]] = Appendix diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 55cc5623d7..b2977883d5 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -385,16 +385,22 @@ public class Person { IMPORTANT: The `@Id` annotation tells the mapper which property you want to use for the MongoDB `_id` property, and the `@Indexed` annotation tells the mapping framework to call `createIndex(…)` on that property of your document, making searches faster. Automatic index creation is only done for types annotated with `@Document`. -WARNING: Auto index creation is turned **OFF** by default and need to be enabled via the configuration (see <>). +WARNING: Auto index creation is **disabled** by default and needs to be enabled through the configuration (see <>). [[mapping.index-creation]] === Index Creation -Spring Data MongoDB can automatically create indexes for entity types annotated with `@Document`. Index creation must be explicitly enabled since version 3.0 to prevent undesired effects with collection lifecyle and performance impact. Indexes are automatically created for the initial entity set on application startup and when accessing an entity type for the first time while the application runs. +Spring Data MongoDB can automatically create indexes for entity types annotated with `@Document`. +Index creation must be explicitly enabled since version 3.0 to prevent undesired effects with collection lifecyle and performance impact. +Indexes are automatically created for the initial entity set on application startup and when accessing an entity type for the first time while the application runs. We generally recommend explicit index creation for application-based control of indexes as Spring Data cannot automatically create indexes for collections that were recreated while the application was running. -`IndexResolver` provides an abstraction for programmatic index definition creation if you want to make use of `@Indexed` annotations such as `@GeoSpatialIndexed`, `@TextIndexed`, `@CompoundIndex`. You can use index definitions with `IndexOperations` to create indexes. A good point in time for index creation is on application startup, specifically after the application context was refreshed, triggered by observing `ContextRefreshedEvent`. This event guarantees that the context is fully initialized. Note that at this time other components, especially bean factories might have access to the MongoDB database. +`IndexResolver` provides an abstraction for programmatic index definition creation if you want to make use of `@Indexed` annotations such as `@GeoSpatialIndexed`, `@TextIndexed`, `@CompoundIndex`. +You can use index definitions with `IndexOperations` to create indexes. +A good point in time for index creation is on application startup, specifically after the application context was refreshed, triggered by observing `ContextRefreshedEvent`. +This event guarantees that the context is fully initialized. +Note that at this time other components, especially bean factories might have access to the MongoDB database. .Programmatic Index Creation for a single Domain Type ==== diff --git a/src/main/asciidoc/reference/mongo-3.adoc b/src/main/asciidoc/reference/mongo-3.adoc deleted file mode 100644 index 2952edf477..0000000000 --- a/src/main/asciidoc/reference/mongo-3.adoc +++ /dev/null @@ -1,127 +0,0 @@ -[[mongo.mongo-3]] -= MongoDB 3.0 Support - -Spring Data MongoDB requires MongoDB Java driver generations 4 when connecting to a MongoDB 2.6/3.0 server running MMap.v1 or a MongoDB server 3.0 using MMap.v1 or the WiredTiger storage engine. - -NOTE: See the driver- and database-specific documentation for major differences between those engines. - -== Using Spring Data MongoDB with MongoDB 3.0 - -The rest of this section describes how to use Spring Data MongoDB with MongoDB 3.0. - -[[mongo.mongo-3.configuration]] -=== Configuration Options - -Some of the configuration options have been changed or removed for the `mongo-java-driver`. The following options are ignored when using the generation 3 driver: - - * `autoConnectRetry` - * `maxAutoConnectRetryTime` - * `slaveOk` - -Generally, you should use the `` and `` elements instead of `` when doing XML based configuration, since those elements provide you with attributes that are only valid for the third generation Java driver. The follwoing example shows how to configure a Mongo client connection: - -[source,xml] ----- - - - - - - - - ----- - -[[mongo.mongo-3.write-concern]] -=== `WriteConcern` and `WriteConcernChecking` - -`WriteConcern.NONE`, which had been used as the default by Spring Data MongoDB, was removed in 3.0. Therefore, in a MongoDB 3 environment, the `WriteConcern` defaults to `WriteConcern.UNACKNOWLEGED`. If `WriteResultChecking.EXCEPTION` is enabled, the `WriteConcern` is altered to `WriteConcern.ACKNOWLEDGED` for write operations. Otherwise, errors during execution would not be thrown correctly, since they are not raised by the driver. - -[[mongo.mongo-3.authentication]] -=== Authentication - -MongoDB Server generation 3 changed the authentication model when connecting to the DB. Therefore, some of the configuration options available for authentication are no longer valid. You should use the `MongoClient`-specific options when setting credentials with `MongoCredential` to provide authentication data, as the following example shows: - -[source,java] ----- -@Configuration -public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { - - @Override - public String getDatabaseName() { - return "database"; - } - - @Override - @Bean - public MongoClient mongoClient() { - return new MongoClient(singletonList(new ServerAddress("127.0.0.1", 27017)), - singletonList(MongoCredential.createCredential("name", "db", "pwd".toCharArray()))); - } -} ----- - -In order to use authentication with XML configuration, you can use the `credentials` attribute on ``, as the following example shows: - -[source,xml] ----- - - - - - - ----- - -[[mongo.mongo-3.validation]] -=== Server-side Validation - -MongoDB supports https://docs.mongodb.com/manual/core/schema-validation/[Schema Validation] as of version 3.2 with query operators -and as of version 3.6 JSON-schema based validation. - -This chapter will point out the specialties for validation in MongoDB and how to apply JSON schema validation. - -[[mongo.mongo-3.validation.json-schema]] -==== JSON Schema Validation - -MongoDB 3.6 allows validation and querying of documents with JSON schema draft 4 (including core specification and validation specification) with some differences. `$jsonSchema` can be used in a document validator (when creating a collection), which enforces that inserted or updated documents are valid against the schema. It can also be used to query for documents with the `find` command or `$match` aggregation stage. - -Spring Data MongoDB supports MongoDB's specific JSON schema implementation to define and use schemas. See <> for further details. - -[[mongo.mongo-3.validation.query-expression]] -==== Query Expression Validation - -In addition to the <>, MongoDB supports (as of version 3.2) validating documents against a given structure described by a query. The structure can be built from `Criteria` objects in the same way as they are used for defining queries. The following example shows how to create and use such a validator: - -[source,java] ----- -Criteria queryExpression = Criteria.where("lastname").ne(null).type(2) - .and("age").ne(null).type(16).gt(0).lte(150); - -Validator validator = Validator.criteria(queryExpression); - -template.createCollection(Person.class, CollectionOptions.empty().validator(validator)); ----- - -NOTE: The field names used within the query expression are mapped to the domain types property names, taking potential `@Field` annotations into account. - -[[mongo.mongo-3.misc]] -=== Miscellaneous Details - -This section covers briefly lists additional things to keep in mind when using the 4.0 driver: - -* `IndexOperations.resetIndexCache()` is no longer supported. -* Any `MapReduceOptions.extraOption` is silently ignored. -* `WriteResult` no longer holds error information but, instead, throws an `Exception`. -* `MongoOperations.executeInSession(…)` no longer calls `requestStart` and `requestDone`. -* Index name generation has become a driver-internal operation. -Spring Data MongoDB still uses the 2.x schema to generate names. -* Some `Exception` messages differ between the generation 2 and 3 servers as well as between the MMap.v1 and WiredTiger storage engines. diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index e10af2975b..48724e2b8a 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -9,7 +9,7 @@ This chapter points out the specialties for repository support for MongoDB. This [[mongo-repo-usage]] == Usage -To access domain entities stored in a MongoDB, you can use our sophisticated repository support that eases implementation quite significantly. To do so, create an interface for your repository, as the following example shows: +To access domain entities stored in a MongoDB, you can use our sophisticated repository support that eases implementation quite significantly.To do so, create an interface for your repository, as the following example shows: .Sample Person entity ==== @@ -28,7 +28,7 @@ public class Person { ---- ==== -Note that the domain type shown in the preceding example has a property named `id` of type `String`. The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as ID types. +Note that the domain type shown in the preceding example has a property named `id` of type `String`.The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as ID types. Please see <> for more information about on how the `id` field is handled in the mapping layer. Now that we have a domain object, we can define an interface that uses it, as follows: @@ -49,7 +49,7 @@ public interface PersonRepository extends PagingAndSortingRepository persons = repository.findAll(PageRequest.of(0, 10)); - assertThat(persons.isFirstPage(), is(true)); + assertThat(persons.isFirstPage()).isTrue(); } } ---- ==== -The preceding example creates an application context with Spring's unit test support, which performs annotation-based dependency injection into test cases. Inside the test method, we use the repository to query the datastore. We hand the repository a `PageRequest` instance that requests the first page of `Person` objects at a page size of 10. +The preceding example creates an application context with Spring's unit test support, which performs annotation-based dependency injection into test cases.Inside the test method, we use the repository to query the datastore.We hand the repository a `PageRequest` instance that requests the first page of `Person` objects at a page size of 10. [[mongodb.repositories.queries]] == Query Methods diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 7ee3ac6240..3fa9431de0 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -4,7 +4,7 @@ The MongoDB support contains a wide range of features: * Spring configuration support with Java-based `@Configuration` classes or an XML namespace for a Mongo driver instance and replica sets. -* `MongoTemplate` helper class that increases productivity when performing common Mongo operations. Includes integrated object mapping between documents and POJOs. +* `MongoTemplate` helper class that increases productivity when performing common Mongo operations.Includes integrated object mapping between documents and POJOs. * Exception translation into Spring's portable Data Access Exception hierarchy. * Feature-rich Object Mapping integrated with Spring's Conversion Service. * Annotation-based mapping metadata that is extensible to support other metadata formats. @@ -669,9 +669,9 @@ public class StringToObjectId { [[mongo-template.type-mapping]] === Type Mapping -MongoDB collections can contain documents that represent instances of a variety of types. This feature can be useful if you store a hierarchy of classes or have a class with a property of type `Object`. In the latter case, the values held inside that property have to be read in correctly when retrieving the object. Thus, we need a mechanism to store type information alongside the actual document. +MongoDB collections can contain documents that represent instances of a variety of types.This feature can be useful if you store a hierarchy of classes or have a class with a property of type `Object`.In the latter case, the values held inside that property have to be read in correctly when retrieving the object.Thus, we need a mechanism to store type information alongside the actual document. -To achieve that, the `MappingMongoConverter` uses a `MongoTypeMapper` abstraction with `DefaultMongoTypeMapper` as its main implementation. Its default behavior to store the fully qualified classname under `_class` inside the document. Type hints are written for top-level documents as well as for every value (if it is a complex type and a subtype of the declared property type). The following example (with a JSON representation at the end) shows how the mapping works: +To achieve that, the `MappingMongoConverter` uses a `MongoTypeMapper` abstraction with `DefaultMongoTypeMapper` as its main implementation.Its default behavior to store the fully qualified classname under `_class` inside the document.Type hints are written for top-level documents as well as for every value (if it is a complex type and a subtype of the declared property type).The following example (with a JSON representation at the end) shows how the mapping works: .Type mapping ==== @@ -697,11 +697,11 @@ mongoTemplate.save(sample); ---- ==== -Spring Data MongoDB stores the type information as the last field for the actual root class as well as for the nested type (because it is complex and a subtype of `Contact`). So, if you now use `mongoTemplate.findAll(Object.class, "sample")`, you can find out that the document stored is a `Sample` instance. You can also find out that the value property is actually a `Person`. +Spring Data MongoDB stores the type information as the last field for the actual root class as well as for the nested type (because it is complex and a subtype of `Contact`).So, if you now use `mongoTemplate.findAll(Object.class, "sample")`, you can find out that the document stored is a `Sample` instance.You can also find out that the value property is actually a `Person`. ==== Customizing Type Mapping -If you want to avoid writing the entire Java class name as type information but would rather like to use a key, you can use the `@TypeAlias` annotation on the entity class. If you need to customize the mapping even more, have a look at the `TypeInformationMapper` interface. An instance of that interface can be configured at the `DefaultMongoTypeMapper`, which can, in turn, be configured on `MappingMongoConverter`. The following example shows how to define a type alias for an entity: +If you want to avoid writing the entire Java class name as type information but would rather like to use a key, you can use the `@TypeAlias` annotation on the entity class.If you need to customize the mapping even more, have a look at the `TypeInformationMapper` interface.An instance of that interface can be configured at the `DefaultMongoTypeMapper`, which can, in turn, be configured on `MappingMongoConverter`.The following example shows how to define a type alias for an entity: .Defining a type alias for an Entity ==== @@ -718,7 +718,9 @@ Note that the resulting document contains `pers` as the value in the `_class` Fi [WARNING] ==== -Type aliases only work if the mapping context is aware of the actual type. The required entity metadata is aquired either on first save or has to be provided via the configurations initial entity set. By default the configuration base package is scanned for potential candidates. +Type aliases only work if the mapping context is aware of the actual type. +The required entity metadata is determined either on first save or has to be provided via the configurations initial entity set. +By default, the configuration class scans the base package for potential candidates. [source,java] ---- @@ -968,14 +970,14 @@ Person oldValue = template.update(Person.class) .apply(update) .findAndModifyValue(); // return's old person object -assertThat(oldValue.getFirstName(), is("Harry")); -assertThat(oldValue.getAge(), is(23)); +assertThat(oldValue.getFirstName()).isEqualTo("Harry"); +assertThat(oldValue.getAge()).isEqualTo(23); Person newValue = template.query(Person.class) .matching(query) .findOneValue(); -assertThat(newValue.getAge(), is(24)); +assertThat(newValue.getAge()).isEqualTo(24); Person newestValue = template.update(Person.class) .matching(query) @@ -983,10 +985,10 @@ Person newestValue = template.update(Person.class) .withOptions(FindAndModifyOptions.options().returnNew(true)) // Now return the newly updated document when updating .findAndModifyValue(); -assertThat(newestValue.getAge(), is(25)); +assertThat(newestValue.getAge()).isEqualTo(25); ---- -The `FindAndModifyOptions` method lets you set the options of `returnNew`, `upsert`, and `remove`. An example extending from the previous code snippet follows: +The `FindAndModifyOptions` method lets you set the options of `returnNew`, `upsert`, and `remove`.An example extending from the previous code snippet follows: [source,java] ---- @@ -996,8 +998,8 @@ Person upserted = template.update(Person.class) .withOptions(FindAndModifyOptions.options().upsert(true).returnNew(true)) .findAndModifyValue() -assertThat(upserted.getFirstName(), is("Mary")); -assertThat(upserted.getAge(), is(1)); +assertThat(upserted.getFirstName()).isEqualTo("Mary"); +assertThat(upserted.getAge()).isOne(); ---- [[mongo-template.aggregation-update]] @@ -1153,7 +1155,7 @@ An `OptimisticLockingFailureException` is raised if a versioned entity cannot be [[mongo.query]] == Querying Documents -You can use the `Query` and `Criteria` classes to express your queries. They have method names that mirror the native MongoDB operator names, such as `lt`, `lte`, `is`, and others. The `Query` and `Criteria` classes follow a fluent API style so that you can chain together multiple method criteria and queries while having easy-to-understand code. To improve readability, static imports let you avoid using the 'new' keyword for creating `Query` and `Criteria` instances. You can also use `BasicQuery` to create `Query` instances from plain JSON Strings, as shown in the following example: +You can use the `Query` and `Criteria` classes to express your queries.They have method names that mirror the native MongoDB operator names, such as `lt`, `lte`, `is`, and others.The `Query` and `Criteria` classes follow a fluent API style so that you can chain together multiple method criteria and queries while having easy-to-understand code.To improve readability, static imports let you avoid using the 'new' keyword for creating `Query` and `Criteria` instances.You can also use `BasicQuery` to create `Query` instances from plain JSON Strings, as shown in the following example: .Creating a Query instance from a plain JSON String ==== @@ -2183,7 +2185,7 @@ mongoOperations.find( [[mongo.query.additional-query-options]] === Additional Query Options -MongoDB offers various ways of applying meta information, like a comment or a batch size, to a query. Using the `Query` API +MongoDB offers various ways of applying meta information, like a comment or a batch size, to a query.Using the `Query` API directly there are several methods for those options. ==== @@ -2213,11 +2215,11 @@ include::query-by-example.adoc[leveloffset=+1] [[mongo.query.count]] == Counting Documents -In pre 3.x versions of SpringData MongoDB the count operation was executed against MongoDBs internal collection statistics. -With the introduction of <> this was no longer possible because statistics would not correctly reflect potential changes during a transaction requiring an aggregation based count approach. -So in 2.x `MongoOperations.count()` would use the collection statistics if no transaction was in progress, and the aggregation variant if so. +In pre-3.x versions of SpringData MongoDB the count operation used MongoDBs internal collection statistics. +With the introduction of <> this was no longer possible because statistics would not correctly reflect potential changes during a transaction requiring an aggregation-based count approach. +So in version 2.x `MongoOperations.count()` would use the collection statistics if no transaction was in progress, and the aggregation variant if so. -As off Spring Data MongoDB 3.x any `count` operation, may it be with our without a filter query, uses the aggregation based count approach via MongoDBs `countDocuments`. +As of Spring Data MongoDB 3.x any `count` operation uses regardless the existence of filter criteria the aggregation-based count approach via MongoDBs `countDocuments`. [NOTE] ==== @@ -2236,7 +2238,7 @@ Therefore a given `Query` will be rewritten for `count` operations using `Reacti <1> Count source query using `$near`. <2> Rewritten query now using `$geoWithin` with `$center`. <3> Count source query using `$near` with `$minDistance` and `$maxDistance`. -<4> Rewritten query now a combination of `$nor` `$geowithin` critierias to work aournd unsupported `$minDistance`. +<4> Rewritten query now a combination of `$nor` `$geowithin` critierias to work around unsupported `$minDistance`. ==== [[mongo.mapreduce]] @@ -2244,12 +2246,12 @@ Therefore a given `Query` will be rewritten for `count` operations using `Reacti You can query MongoDB by using Map-Reduce, which is useful for batch processing, for data aggregation, and for when the query language does not fulfill your needs. -Spring provides integration with MongoDB's Map-Reduce by providing methods on `MongoOperations` to simplify the creation and execution of Map-Reduce operations. It can convert the results of a Map-Reduce operation to a POJO and integrates with Spring's https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#resources[Resource abstraction]. This lets you place your JavaScript files on the file system, classpath, HTTP server, or any other Spring Resource implementation and then reference the JavaScript resources through an easy URI style syntax -- for example, `classpath:reduce.js;`. Externalizing JavaScript code in files is often preferable to embedding them as Java strings in your code. Note that you can still pass JavaScript code as Java strings if you prefer. +Spring provides integration with MongoDB's Map-Reduce by providing methods on `MongoOperations` to simplify the creation and execution of Map-Reduce operations.It can convert the results of a Map-Reduce operation to a POJO and integrates with Spring's https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#resources[Resource abstraction].This lets you place your JavaScript files on the file system, classpath, HTTP server, or any other Spring Resource implementation and then reference the JavaScript resources through an easy URI style syntax -- for example, `classpath:reduce.js;`.Externalizing JavaScript code in files is often preferable to embedding them as Java strings in your code.Note that you can still pass JavaScript code as Java strings if you prefer. [[mongo.mapreduce.example]] === Example Usage -To understand how to perform Map-Reduce operations, we use an example from the book, _MongoDB - The Definitive Guide_ footnote:[Kristina Chodorow. _MongoDB - The Definitive Guide_. O'Reilly Media, 2013]. In this example, we create three documents that have the values [a,b], [b,c], and [c,d], respectively. The values in each document are associated with the key, 'x', as the following example shows (assume these documents are in a collection named `jmr1`): +To understand how to perform Map-Reduce operations, we use an example from the book, _MongoDB - The Definitive Guide_ footnote:[Kristina Chodorow. _MongoDB - The Definitive Guide_. O'Reilly Media, 2013].In this example, we create three documents that have the values [a,b], [b,c], and [c,d], respectively.The values in each document are associated with the key, 'x', as the following example shows (assume these documents are in a collection named `jmr1`): [source] ---- @@ -2311,7 +2313,7 @@ ValueObject [id=c, value=2.0] ValueObject [id=d, value=1.0] ---- -The `MapReduceResults` class implements `Iterable` and provides access to the raw output and timing and count statistics. The following listing shows the `ValueObject` class: +The `MapReduceResults` class implements `Iterable` and provides access to the raw output and timing and count statistics.The following listing shows the `ValueObject` class: [source,java] ---- @@ -2339,7 +2341,7 @@ public class ValueObject { } ---- -By default, the output type of `INLINE` is used so that you need not specify an output collection. To specify additional Map-Reduce options, use an overloaded method that takes an additional `MapReduceOptions` argument. The class `MapReduceOptions` has a fluent API, so adding additional options can be done in a compact syntax. The following example sets the output collection to `jmr1_out` (note that setting only the output collection assumes a default output type of `REPLACE`): +By default, the output type of `INLINE` is used so that you need not specify an output collection.To specify additional Map-Reduce options, use an overloaded method that takes an additional `MapReduceOptions` argument.The class `MapReduceOptions` has a fluent API, so adding additional options can be done in a compact syntax.The following example sets the output collection to `jmr1_out` (note that setting only the output collection assumes a default output type of `REPLACE`): [source,java] ---- @@ -2355,7 +2357,7 @@ MapReduceResults results = mongoOperations.mapReduce("jmr1", "class options().outputCollection("jmr1_out"), ValueObject.class); ---- -You can also specify a query to reduce the set of data that is fed into the Map-Reduce operation. The following example removes the document that contains [a,b] from consideration for Map-Reduce operations: +You can also specify a query to reduce the set of data that is fed into the Map-Reduce operation.The following example removes the document that contains [a,b] from consideration for Map-Reduce operations: [source,java] ---- diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index df1bcb092d..281aa9ba18 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -6,6 +6,16 @@ The 4.0 MongoDB Java Driver does no longer support certain features that have al Some of the changes affect the initial setup configuration as well as compile/runtime features. We summarized the most typical changes one might encounter. +Things to keep in mind when using the 4.0 driver: + +* `IndexOperations.resetIndexCache()` is no longer supported. +* Any `MapReduceOptions.extraOption` is silently ignored. +* `WriteResult` no longer holds error information but, instead, throws an `Exception`. +* `MongoOperations.executeInSession(…)` no longer calls `requestStart` and `requestDone`. +* Index name generation has become a driver-internal operation. +Spring Data MongoDB still uses the 2.x schema to generate names. +* Some `Exception` messages differ between the generation 2 and 3 servers as well as between the MMap.v1 and WiredTiger storage engines. + == Dependency Changes Instead of the single artifact uber-jar `mongo-java-driver`, imports are now split to include separate artifacts: From 0345abb5f82c7b3e9c13f8037d9c974b17b5c910 Mon Sep 17 00:00:00 2001 From: Florian Bernard Date: Mon, 30 Mar 2020 16:25:48 +0200 Subject: [PATCH 0166/1381] DATAMONGO-2509 - Add missing Query constructor in reference documentation. Original pull request: #846. --- src/main/asciidoc/reference/mongodb.adoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 3fa9431de0..9e076d6e3e 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2161,10 +2161,11 @@ mongoOperations.find( ) mongoOperations.find( - Criteria().andOperator( - Book::price gt 5, - Book::price lt 10 - ) + Query( + Criteria().andOperator( + Book::price gt 5, + Book::price lt 10 + )) ) // Binary operators From c2b0090ff11eba855626b92b198c88789c275d72 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 11 May 2020 17:00:39 +0200 Subject: [PATCH 0167/1381] DATAMONGO-2541 - Upgrade to MongoDB 4.0.3 Drivers. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e5e41bf08c..e23cd748b3 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 4.0.2 + 4.0.3 ${mongo} 1.19 From 93a27f80a30290afa72e036ef1415113808f0618 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 12 May 2020 12:27:47 +0200 Subject: [PATCH 0168/1381] DATAMONGO-2534 - Updated changelog. --- src/main/resources/changelog.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 21d3ca9d00..5b7cdacdbe 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,15 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.0.RELEASE (2020-05-12) +--------------------------------------------- +* DATAMONGO-2541 - Upgrade to MongoDB 4.0.3 Drivers. +* DATAMONGO-2535 - Remove Travis CI. +* DATAMONGO-2534 - Release 3.0 GA (Neumann). +* DATAMONGO-2509 - Polish documentation for 3.0 release. +* DATAMONGO-365 - Example 5.5. of reference documentation uses deprecated function. + + Changes in version 3.0.0.RC2 (2020-04-28) ----------------------------------------- * DATAMONGO-2531 - Fix MongoClientSettings UUID configuration hook in MongoConfigurationSupport. @@ -3019,3 +3028,4 @@ Repository + From 62bfde2b6b68c76dd81e315e4c21e4639952c491 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 12 May 2020 12:27:59 +0200 Subject: [PATCH 0169/1381] DATAMONGO-2534 - Prepare 3.0 GA (Neumann). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index e23cd748b3..a9e1edc271 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.BUILD-SNAPSHOT + 2.3.0.RELEASE @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.BUILD-SNAPSHOT + 2.3.0.RELEASE 4.0.3 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-release + https://repo.spring.io/libs-release sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index c895699a72..c42a8a0b93 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 RC2 +Spring Data MongoDB 3.0 GA Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -14,3 +14,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From f88d1de068e160f4cc5b05aeabb96c7f636e6ef5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 12 May 2020 12:28:23 +0200 Subject: [PATCH 0170/1381] DATAMONGO-2534 - Release version 3.0 GA (Neumann). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index a9e1edc271..ce0fa5e15d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RELEASE pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index b5dba6f53e..fa6beb5778 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RELEASE ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index dbb3854812..f0cb34d5f3 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RELEASE ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 872db5d428..6ede5b361b 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.BUILD-SNAPSHOT + 3.0.0.RELEASE ../pom.xml From c6a86226e013d6288c7b1b502cf0402458c6a268 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 12 May 2020 12:40:28 +0200 Subject: [PATCH 0171/1381] DATAMONGO-2534 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ce0fa5e15d..ff9ad9802e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RELEASE + 3.1.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index fa6beb5778..a85b081e26 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RELEASE + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index f0cb34d5f3..33014c7c4f 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RELEASE + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 6ede5b361b..c85d971ad8 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.0.0.RELEASE + 3.1.0-SNAPSHOT ../pom.xml From 3fda554f81ffbc47250b5d253ed8b7d9110f2651 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 12 May 2020 12:40:30 +0200 Subject: [PATCH 0172/1381] DATAMONGO-2534 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ff9ad9802e..f59b2c8bf4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.3.0.RELEASE + 2.4.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.3.0.RELEASE + 2.4.0-SNAPSHOT 4.0.3 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-release - https://repo.spring.io/libs-release + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 26fa0c8285ec98904648a0f6f3a520cc7854a1ad Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 8 May 2020 12:38:30 +0200 Subject: [PATCH 0173/1381] DATAMONGO-2538 - Delombok source files. Original pull request: #861. --- .../data/mongodb/core/AggregationUtil.java | 10 +- .../data/mongodb/core/ChangeStreamEvent.java | 31 +++- .../mongodb/core/ChangeStreamOptions.java | 42 ++++- .../data/mongodb/core/CollectionOptions.java | 10 +- .../mongodb/core/DefaultBulkOperations.java | 146 ++++++++++++++++-- .../data/mongodb/core/EntityOperations.java | 47 ++++-- ...ExecutableAggregationOperationSupport.java | 31 ++-- .../core/ExecutableFindOperationSupport.java | 35 +++-- .../ExecutableInsertOperationSupport.java | 30 ++-- .../ExecutableMapReduceOperationSupport.java | 12 +- .../ExecutableRemoveOperationSupport.java | 29 ++-- .../ExecutableUpdateOperationSupport.java | 47 +++--- .../data/mongodb/core/MappedDocument.java | 20 ++- .../core/MongoDatabaseFactorySupport.java | 50 +++++- .../data/mongodb/core/MongoTemplate.java | 61 +++++--- .../data/mongodb/core/PropertyOperations.java | 8 +- .../ReactiveAggregationOperationSupport.java | 23 +-- .../core/ReactiveFindOperationSupport.java | 34 ++-- .../core/ReactiveInsertOperationSupport.java | 26 ++-- .../ReactiveMapReduceOperationSupport.java | 9 +- .../mongodb/core/ReactiveMongoTemplate.java | 60 +++++-- .../core/ReactiveRemoveOperationSupport.java | 29 ++-- .../core/ReactiveUpdateOperationSupport.java | 51 +++--- .../SimpleReactiveMongoDatabaseFactory.java | 50 +++++- .../MongoPersistentEntityIndexResolver.java | 34 +++- .../core/index/PartialIndexFilter.java | 18 +-- .../core/messaging/ChangeStreamTask.java | 9 +- .../DefaultMessageListenerContainer.java | 28 +++- .../LazyMappingDelegatingMessage.java | 7 +- .../data/mongodb/core/messaging/Message.java | 34 +++- .../mongodb/core/messaging/SimpleMessage.java | 37 ++++- .../data/mongodb/core/query/Collation.java | 43 ++++-- .../data/mongodb/core/query/Field.java | 40 ++++- .../core/query/UntypedExampleMatcher.java | 32 +++- .../core/schema/DefaultMongoJsonSchema.java | 13 +- .../core/schema/DocumentJsonSchema.java | 13 +- .../mongodb/core/schema/JsonSchemaObject.java | 51 +++++- .../core/schema/JsonSchemaProperty.java | 8 +- .../core/schema/UntypedJsonSchemaObject.java | 14 +- .../core/validation/CriteriaValidator.java | 28 +++- .../core/validation/DocumentValidator.java | 29 +++- .../core/validation/JsonSchemaValidator.java | 29 +++- .../repository/query/AggregationUtils.java | 9 +- .../mongodb/repository/query/BooleanUtil.java | 9 +- .../repository/query/CollationUtils.java | 9 +- .../repository/query/MongoQueryExecution.java | 66 ++++++-- .../query/ReactiveMongoQueryExecution.java | 52 +++++-- .../query/SimpleMongoEntityMetadata.java | 8 +- .../ReactiveMongoRepositoryFactory.java | 13 +- .../SimpleReactiveMongoRepository.java | 17 +- .../util/json/ParameterBindingJsonReader.java | 35 ++++- 51 files changed, 1166 insertions(+), 410 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java index e67773c1fc..0f956a317b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AllArgsConstructor; - import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -49,12 +47,18 @@ * @author Mark Paluch * @since 2.1 */ -@AllArgsConstructor class AggregationUtil { QueryMapper queryMapper; MappingContext, MongoPersistentProperty> mappingContext; + AggregationUtil(QueryMapper queryMapper, + MappingContext, MongoPersistentProperty> mappingContext) { + + this.queryMapper = queryMapper; + this.mappingContext = mappingContext; + } + /** * Prepare the {@link AggregationOperationContext} for a given aggregation by either returning the context itself it * is not {@literal null}, create a {@link TypeBasedAggregationOperationContext} if the aggregation contains type diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java index 8e1d3523c5..a86dbc903f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.EqualsAndHashCode; - import java.time.Instant; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; @@ -27,6 +25,7 @@ import org.springframework.data.mongodb.core.messaging.Message; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.OperationType; @@ -39,7 +38,6 @@ * @author Mark Paluch * @since 2.1 */ -@EqualsAndHashCode public class ChangeStreamEvent { @SuppressWarnings("rawtypes") // @@ -187,8 +185,8 @@ private Object doGetConverted(Document fullDocument) { return CONVERTED_UPDATER.compareAndSet(this, null, result) ? result : CONVERTED_UPDATER.get(this); } - throw new IllegalArgumentException(String.format("No converter found capable of converting %s to %s", - fullDocument.getClass(), targetType)); + throw new IllegalArgumentException( + String.format("No converter found capable of converting %s to %s", fullDocument.getClass(), targetType)); } /* @@ -199,4 +197,27 @@ private Object doGetConverted(Document fullDocument) { public String toString() { return "ChangeStreamEvent {" + "raw=" + raw + ", targetType=" + targetType + '}'; } + + @Override + public boolean equals(Object o) { + + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ChangeStreamEvent that = (ChangeStreamEvent) o; + + if (!ObjectUtils.nullSafeEquals(this.raw, that.raw)) { + return false; + } + return ObjectUtils.nullSafeEquals(this.targetType, that.targetType); + } + + @Override + public int hashCode() { + int result = raw != null ? raw.hashCode() : 0; + result = 31 * result + ObjectUtils.nullSafeHashCode(targetType); + return result; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java index 535e40a216..65f27f915f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.EqualsAndHashCode; - import java.time.Instant; import java.util.Arrays; import java.util.Optional; @@ -25,7 +23,6 @@ import org.bson.BsonTimestamp; import org.bson.BsonValue; import org.bson.Document; - import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.lang.Nullable; @@ -45,7 +42,6 @@ * @author Mark Paluch * @since 2.1 */ -@EqualsAndHashCode public class ChangeStreamOptions { private @Nullable Object filter; @@ -156,6 +152,44 @@ private static Object doGetTimestamp(Object timestamp, Class targetType) + ObjectUtils.nullSafeClassName(timestamp)); } + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ChangeStreamOptions that = (ChangeStreamOptions) o; + + if (!ObjectUtils.nullSafeEquals(this.filter, that.filter)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.resumeToken, that.resumeToken)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.fullDocumentLookup, that.fullDocumentLookup)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.collation, that.collation)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.resumeTimestamp, that.resumeTimestamp)) { + return false; + } + return resume == that.resume; + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(filter); + result = 31 * result + ObjectUtils.nullSafeHashCode(resumeToken); + result = 31 * result + ObjectUtils.nullSafeHashCode(fullDocumentLookup); + result = 31 * result + ObjectUtils.nullSafeHashCode(collation); + result = 31 * result + ObjectUtils.nullSafeHashCode(resumeTimestamp); + result = 31 * result + ObjectUtils.nullSafeHashCode(resume); + return result; + } + /** * @author Christoph Strobl * @since 2.2 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 77833c6ada..8e4f1b1f48 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 @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.RequiredArgsConstructor; - import java.util.Optional; import org.springframework.data.mongodb.core.query.Collation; @@ -312,7 +310,6 @@ public Optional getValidationOptions() { * @author Andreas Zink * @since 2.1 */ - @RequiredArgsConstructor public static class ValidationOptions { private static final ValidationOptions NONE = new ValidationOptions(null, null, null); @@ -321,6 +318,13 @@ public static class ValidationOptions { private final @Nullable ValidationLevel validationLevel; private final @Nullable ValidationAction validationAction; + public ValidationOptions(Validator validator, ValidationLevel validationLevel, ValidationAction validationAction) { + + this.validator = validator; + this.validationLevel = validationLevel; + this.validationAction = validationAction; + } + /** * Create an empty {@link ValidationOptions}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index bbd99d3d8d..10518301f2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.NonNull; -import lombok.Value; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -47,6 +44,7 @@ import org.springframework.data.util.Pair; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import com.mongodb.WriteConcern; import com.mongodb.bulk.BulkWriteResult; @@ -547,15 +545,93 @@ private static UpdateOptions computeUpdateOptions(Query filterQuery, UpdateDefin * @author Christoph Strobl * @since 2.0 */ - @Value - static class BulkOperationContext { + static final class BulkOperationContext { + + private final BulkMode bulkMode; + private final Optional> entity; + private final QueryMapper queryMapper; + private final UpdateMapper updateMapper; + private final ApplicationEventPublisher eventPublisher; + private final EntityCallbacks entityCallbacks; + + BulkOperationContext(BulkOperations.BulkMode bulkMode, Optional> entity, + QueryMapper queryMapper, UpdateMapper updateMapper, ApplicationEventPublisher eventPublisher, + EntityCallbacks entityCallbacks) { + + this.bulkMode = bulkMode; + this.entity = entity; + this.queryMapper = queryMapper; + this.updateMapper = updateMapper; + this.eventPublisher = eventPublisher; + this.entityCallbacks = entityCallbacks; + } + + public BulkMode getBulkMode() { + return this.bulkMode; + } + + public Optional> getEntity() { + return this.entity; + } + + public QueryMapper getQueryMapper() { + return this.queryMapper; + } + + public UpdateMapper getUpdateMapper() { + return this.updateMapper; + } + + public ApplicationEventPublisher getEventPublisher() { + return this.eventPublisher; + } + + public EntityCallbacks getEntityCallbacks() { + return this.entityCallbacks; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + BulkOperationContext that = (BulkOperationContext) o; + + if (bulkMode != that.bulkMode) + return false; + if (!ObjectUtils.nullSafeEquals(this.entity, that.entity)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.queryMapper, that.queryMapper)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.updateMapper, that.updateMapper)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.eventPublisher, that.eventPublisher)) { + return false; + } + return ObjectUtils.nullSafeEquals(this.entityCallbacks, that.entityCallbacks); + } - @NonNull BulkMode bulkMode; - @NonNull Optional> entity; - @NonNull QueryMapper queryMapper; - @NonNull UpdateMapper updateMapper; - ApplicationEventPublisher eventPublisher; - EntityCallbacks entityCallbacks; + @Override + public int hashCode() { + int result = bulkMode != null ? bulkMode.hashCode() : 0; + result = 31 * result + ObjectUtils.nullSafeHashCode(entity); + result = 31 * result + ObjectUtils.nullSafeHashCode(queryMapper); + result = 31 * result + ObjectUtils.nullSafeHashCode(updateMapper); + result = 31 * result + ObjectUtils.nullSafeHashCode(eventPublisher); + result = 31 * result + ObjectUtils.nullSafeHashCode(entityCallbacks); + return result; + } + + public String toString() { + return "DefaultBulkOperations.BulkOperationContext(bulkMode=" + this.getBulkMode() + ", entity=" + + this.getEntity() + ", queryMapper=" + this.getQueryMapper() + ", updateMapper=" + this.getUpdateMapper() + + ", eventPublisher=" + this.getEventPublisher() + ", entityCallbacks=" + this.getEntityCallbacks() + ")"; + } } /** @@ -564,10 +640,50 @@ static class BulkOperationContext { * @since 2.2 * @author Christoph Strobl */ - @Value - private static class SourceAwareWriteModelHolder { + private static final class SourceAwareWriteModelHolder { + + private final Object source; + private final WriteModel model; + + SourceAwareWriteModelHolder(Object source, WriteModel model) { - Object source; - WriteModel model; + this.source = source; + this.model = model; + } + + public Object getSource() { + return this.source; + } + + public WriteModel getModel() { + return this.model; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + SourceAwareWriteModelHolder that = (SourceAwareWriteModelHolder) o; + + if (!ObjectUtils.nullSafeEquals(this.source, that.source)) { + return false; + } + return ObjectUtils.nullSafeEquals(this.model, that.model); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(model); + result = 31 * result + ObjectUtils.nullSafeHashCode(source); + return result; + } + + public String toString() { + return "DefaultBulkOperations.SourceAwareWriteModelHolder(source=" + this.getSource() + ", model=" + + this.getModel() + ")"; + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index a7cbf879ed..db1d04d244 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -15,10 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.Collection; import java.util.Map; import java.util.Optional; @@ -55,12 +51,15 @@ * @see MongoTemplate * @see ReactiveMongoTemplate */ -@RequiredArgsConstructor class EntityOperations { private static final String ID_FIELD = "_id"; - private final @NonNull MappingContext, MongoPersistentProperty> context; + private final MappingContext, MongoPersistentProperty> context; + + EntityOperations(MappingContext, MongoPersistentProperty> context) { + this.context = context; + } /** * Creates a new {@link Entity} for the given bean. @@ -69,7 +68,7 @@ class EntityOperations { * @return new instance of {@link Entity}. */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public Entity forEntity(T entity) { + Entity forEntity(T entity) { Assert.notNull(entity, "Bean must not be null!"); @@ -92,7 +91,7 @@ public Entity forEntity(T entity) { * @return new instance of {@link AdaptibleEntity}. */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public AdaptibleEntity forEntity(T entity, ConversionService conversionService) { + AdaptibleEntity forEntity(T entity, ConversionService conversionService) { Assert.notNull(entity, "Bean must not be null!"); Assert.notNull(conversionService, "ConversionService must not be null!"); @@ -346,11 +345,14 @@ interface AdaptibleEntity extends Entity { Number getVersion(); } - @RequiredArgsConstructor private static class UnmappedEntity> implements AdaptibleEntity { private final T map; + protected UnmappedEntity(T map) { + this.map = map; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.EntityOperations.PersistableSource#getIdPropertyName() @@ -460,7 +462,7 @@ public boolean isNew() { private static class SimpleMappedEntity> extends UnmappedEntity { - SimpleMappedEntity(T map) { + protected SimpleMappedEntity(T map) { super(map); } @@ -483,12 +485,19 @@ public MappedDocument toMappedDocument(MongoWriter writer) { } } - @RequiredArgsConstructor(access = AccessLevel.PROTECTED) private static class MappedEntity implements Entity { - private final @NonNull MongoPersistentEntity entity; - private final @NonNull IdentifierAccessor idAccessor; - private final @NonNull PersistentPropertyAccessor propertyAccessor; + private final MongoPersistentEntity entity; + private final IdentifierAccessor idAccessor; + private final PersistentPropertyAccessor propertyAccessor; + + protected MappedEntity(MongoPersistentEntity entity, IdentifierAccessor idAccessor, + PersistentPropertyAccessor propertyAccessor) { + + this.entity = entity; + this.idAccessor = idAccessor; + this.propertyAccessor = propertyAccessor; + } private static MappedEntity of(T bean, MappingContext, MongoPersistentProperty> context) { @@ -759,11 +768,12 @@ interface TypedOperations { * {@link TypedOperations} for generic entities that are not represented with {@link PersistentEntity} (e.g. custom * conversions). */ - @RequiredArgsConstructor enum UntypedOperations implements TypedOperations { INSTANCE; + UntypedOperations() {} + @SuppressWarnings({ "unchecked", "rawtypes" }) public static TypedOperations instance() { return (TypedOperations) INSTANCE; @@ -798,10 +808,13 @@ public Optional getCollation(Query query) { * * @param */ - @RequiredArgsConstructor static class TypedEntityOperations implements TypedOperations { - private final @NonNull MongoPersistentEntity entity; + private final MongoPersistentEntity entity; + + protected TypedEntityOperations(MongoPersistentEntity entity) { + this.entity = entity; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java index 76ff13a02a..0317b01890 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java @@ -15,16 +15,10 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; - import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.util.CloseableIterator; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -35,10 +29,13 @@ * @author Mark Paluch * @since 2.0 */ -@RequiredArgsConstructor class ExecutableAggregationOperationSupport implements ExecutableAggregationOperation { - private final @NonNull MongoTemplate template; + private final MongoTemplate template; + + ExecutableAggregationOperationSupport(MongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -56,15 +53,21 @@ public ExecutableAggregation aggregateAndReturn(Class domainType) { * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ExecutableAggregationSupport implements AggregationWithAggregation, ExecutableAggregation, TerminatingAggregation { - @NonNull MongoTemplate template; - @NonNull Class domainType; - @Nullable Aggregation aggregation; - @Nullable String collection; + private final MongoTemplate template; + private final Class domainType; + private final Aggregation aggregation; + private final String collection; + + public ExecutableAggregationSupport(MongoTemplate template, Class domainType, Aggregation aggregation, + String collection) { + this.template = template; + this.domainType = domainType; + this.aggregation = aggregation; + this.collection = collection; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java index eac01e5298..758112ef96 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java @@ -15,12 +15,6 @@ */ package org.springframework.data.mongodb.core; -import com.mongodb.ReadPreference; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; - import java.util.List; import java.util.Optional; import java.util.stream.Stream; @@ -37,6 +31,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; +import com.mongodb.ReadPreference; import com.mongodb.client.FindIterable; /** @@ -46,12 +41,15 @@ * @author Mark Paluch * @since 2.0 */ -@RequiredArgsConstructor class ExecutableFindOperationSupport implements ExecutableFindOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull MongoTemplate template; + private final MongoTemplate template; + + ExecutableFindOperationSupport(MongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -70,16 +68,23 @@ public ExecutableFind query(Class domainType) { * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ExecutableFindSupport implements ExecutableFind, FindWithCollection, FindWithProjection, FindWithQuery { - @NonNull MongoTemplate template; - @NonNull Class domainType; - Class returnType; - @Nullable String collection; - Query query; + private final MongoTemplate template; + private final Class domainType; + private final Class returnType; + @Nullable private final String collection; + private final Query query; + + ExecutableFindSupport(MongoTemplate template, Class domainType, Class returnType, + String collection, Query query) { + this.template = template; + this.domainType = domainType; + this.returnType = returnType; + this.collection = collection; + this.query = query; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java index a22625f7ac..fe4a0a8ea3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java @@ -15,11 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; - import java.util.ArrayList; import java.util.Collection; @@ -37,10 +32,13 @@ * @author Mark Paluch * @since 2.0 */ -@RequiredArgsConstructor class ExecutableInsertOperationSupport implements ExecutableInsertOperation { - private final @NonNull MongoTemplate template; + private final MongoTemplate template; + + ExecutableInsertOperationSupport(MongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -58,14 +56,20 @@ public ExecutableInsert insert(Class domainType) { * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ExecutableInsertSupport implements ExecutableInsert { - @NonNull MongoTemplate template; - @NonNull Class domainType; - @Nullable String collection; - @Nullable BulkMode bulkMode; + private final MongoTemplate template; + private final Class domainType; + @Nullable private final String collection; + @Nullable private final BulkMode bulkMode; + + ExecutableInsertSupport(MongoTemplate template, Class domainType, String collection, BulkMode bulkMode) { + + this.template = template; + this.domainType = domainType; + this.collection = collection; + this.bulkMode = bulkMode; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java index 57e9d38cc4..96f581d55f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.List; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; @@ -32,12 +29,17 @@ * @author Christoph Strobl * @since 2.1 */ -@RequiredArgsConstructor class ExecutableMapReduceOperationSupport implements ExecutableMapReduceOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull MongoTemplate template; + private final MongoTemplate template; + + ExecutableMapReduceOperationSupport(MongoTemplate template) { + + Assert.notNull(template, "Template must not be null!"); + this.template = template; + } /* * (non-Javascript) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java index edba892a03..7b39522066 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java @@ -15,11 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; - import java.util.List; import org.springframework.data.mongodb.core.query.Query; @@ -36,12 +31,15 @@ * @author Mark Paluch * @since 2.0 */ -@RequiredArgsConstructor class ExecutableRemoveOperationSupport implements ExecutableRemoveOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull MongoTemplate tempate; + private final MongoTemplate tempate; + + public ExecutableRemoveOperationSupport(MongoTemplate tempate) { + this.tempate = tempate; + } /* * (non-Javadoc) @@ -59,14 +57,19 @@ public ExecutableRemove remove(Class domainType) { * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ExecutableRemoveSupport implements ExecutableRemove, RemoveWithCollection { - @NonNull MongoTemplate template; - @NonNull Class domainType; - Query query; - @Nullable String collection; + private final MongoTemplate template; + private final Class domainType; + private final Query query; + @Nullable private final String collection; + + public ExecutableRemoveSupport(MongoTemplate template, Class domainType, Query query, String collection) { + this.template = template; + this.domainType = domainType; + this.query = query; + this.collection = collection; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java index 0d84c56f9a..f5ed3740eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java @@ -15,11 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; - import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.lang.Nullable; @@ -35,12 +30,15 @@ * @author Mark Paluch * @since 2.0 */ -@RequiredArgsConstructor class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull MongoTemplate template; + private final MongoTemplate template; + + ExecutableUpdateOperationSupport(MongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -58,21 +56,34 @@ public ExecutableUpdate update(Class domainType) { * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ExecutableUpdateSupport implements ExecutableUpdate, UpdateWithCollection, UpdateWithQuery, TerminatingUpdate, FindAndReplaceWithOptions, TerminatingFindAndReplace, FindAndReplaceWithProjection { - @NonNull MongoTemplate template; - @NonNull Class domainType; - Query query; - @Nullable UpdateDefinition update; - @Nullable String collection; - @Nullable FindAndModifyOptions findAndModifyOptions; - @Nullable FindAndReplaceOptions findAndReplaceOptions; - @Nullable Object replacement; - @NonNull Class targetType; + private final MongoTemplate template; + private final Class domainType; + private final Query query; + @Nullable private final UpdateDefinition update; + @Nullable private final String collection; + @Nullable private final FindAndModifyOptions findAndModifyOptions; + @Nullable private final FindAndReplaceOptions findAndReplaceOptions; + @Nullable private final Object replacement; + private final Class targetType; + + ExecutableUpdateSupport(MongoTemplate template, Class domainType, Query query, UpdateDefinition update, + String collection, FindAndModifyOptions findAndModifyOptions, FindAndReplaceOptions findAndReplaceOptions, + Object replacement, Class targetType) { + + this.template = template; + this.domainType = domainType; + this.query = query; + this.update = update; + this.collection = collection; + this.findAndModifyOptions = findAndModifyOptions; + this.findAndReplaceOptions = findAndReplaceOptions; + this.replacement = replacement; + this.targetType = targetType; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java index 7df9503caa..2c14a5bafd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - import java.util.Collection; import java.util.List; @@ -27,8 +24,6 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.util.StreamUtils; -import com.mongodb.client.model.Filters; - /** * A MongoDB document in its mapped state. I.e. after a source document has been mapped using mapping information of the * entity the source document was supposed to represent. @@ -36,13 +31,20 @@ * @author Oliver Gierke * @since 2.1 */ -@RequiredArgsConstructor(staticName = "of") public class MappedDocument { private static final String ID_FIELD = "_id"; private static final Document ID_ONLY_PROJECTION = new Document(ID_FIELD, 1); - private final @Getter Document document; + private final Document document; + + private MappedDocument(Document document) { + this.document = document; + } + + public static MappedDocument of(Document document) { + return new MappedDocument(document); + } public static Document getIdOnlyProjection() { return ID_ONLY_PROJECTION; @@ -91,6 +93,10 @@ public UpdateDefinition updateWithoutId() { return new MappedUpdate(Update.fromDocument(document, ID_FIELD)); } + public Document getDocument() { + return this.document; + } + /** * An {@link UpdateDefinition} that indicates that the {@link #getUpdateObject() update object} has already been * mapped to the specific domain type. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java index 60f1ed56a9..c716015eee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.Value; - import org.springframework.aop.framework.ProxyFactory; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -24,6 +22,7 @@ import org.springframework.data.mongodb.SessionAwareMethodInterceptor; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import com.mongodb.ClientSessionOptions; import com.mongodb.WriteConcern; @@ -171,11 +170,15 @@ protected String getDefaultDatabaseName() { * @author Christoph Strobl * @since 2.1 */ - @Value - static class ClientSessionBoundMongoDbFactory implements MongoDatabaseFactory { + static final class ClientSessionBoundMongoDbFactory implements MongoDatabaseFactory { + + private final ClientSession session; + private final MongoDatabaseFactory delegate; - ClientSession session; - MongoDatabaseFactory delegate; + public ClientSessionBoundMongoDbFactory(ClientSession session, MongoDatabaseFactory delegate) { + this.session = session; + this.delegate = delegate; + } /* * (non-Javadoc) @@ -256,5 +259,40 @@ private T createProxyInstance(com.mongodb.session.ClientSession session, T t return targetType.cast(factory.getProxy()); } + + public ClientSession getSession() { + return this.session; + } + + public MongoDatabaseFactory getDelegate() { + return this.delegate; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ClientSessionBoundMongoDbFactory that = (ClientSessionBoundMongoDbFactory) o; + + if (!ObjectUtils.nullSafeEquals(this.session, that.session)) { + return false; + } + return ObjectUtils.nullSafeEquals(this.delegate, that.delegate); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(this.session); + result = 31 * result + ObjectUtils.nullSafeHashCode(this.delegate); + return result; + } + + public String toString() { + return "MongoDatabaseFactorySupport.ClientSessionBoundMongoDbFactory(session=" + this.getSession() + ", delegate=" + + this.getDelegate() + ")"; + } } } 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 b70ddcbb60..3dc23dd945 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 @@ -17,11 +17,6 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; @@ -33,7 +28,6 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -2950,12 +2944,17 @@ public FindIterable doInCollection(MongoCollection collectio * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor private class ExistsCallback implements CollectionCallback { private final Document mappedQuery; private final com.mongodb.client.model.Collation collation; + ExistsCallback(Document mappedQuery, com.mongodb.client.model.Collation collation) { + + this.mappedQuery = mappedQuery; + this.collation = collation; + } + @Override public Boolean doInCollection(MongoCollection collection) throws MongoException, DataAccessException { @@ -2977,7 +2976,7 @@ private static class FindAndRemoveCallback implements CollectionCallback collation; - public FindAndRemoveCallback(Document query, Document fields, Document sort, @Nullable Collation collation) { + FindAndRemoveCallback(Document query, Document fields, Document sort, @Nullable Collation collation) { this.query = query; this.fields = fields; @@ -3003,8 +3002,9 @@ private static class FindAndModifyCallback implements CollectionCallback arrayFilters; private final FindAndModifyOptions options; - public FindAndModifyCallback(Document query, Document fields, Document sort, Object update, + FindAndModifyCallback(Document query, Document fields, Document sort, Object update, List arrayFilters, FindAndModifyOptions options) { + this.query = query; this.fields = fields; this.sort = sort; @@ -3113,13 +3113,19 @@ interface DocumentCallback { * @author Christoph Strobl * @author Roman Puchkovskiy */ - @RequiredArgsConstructor private class ReadDocumentCallback implements DocumentCallback { - private final @NonNull EntityReader reader; - private final @NonNull Class type; + private final EntityReader reader; + private final Class type; private final String collectionName; + ReadDocumentCallback(EntityReader reader, Class type, String collectionName) { + + this.reader = reader; + this.type = type; + this.collectionName = collectionName; + } + @Nullable public T doWith(@Nullable Document document) { @@ -3147,13 +3153,21 @@ public T doWith(@Nullable Document document) { * @param * @since 2.0 */ - @RequiredArgsConstructor private class ProjectingReadCallback implements DocumentCallback { - private final @NonNull EntityReader reader; - private final @NonNull Class entityType; - private final @NonNull Class targetType; - private final @NonNull String collectionName; + private final EntityReader reader; + private final Class entityType; + private final Class targetType; + private final String collectionName; + + ProjectingReadCallback(EntityReader reader, Class entityType, Class targetType, + String collectionName) { + + this.reader = reader; + this.entityType = entityType; + this.targetType = targetType; + this.collectionName = collectionName; + } /* * (non-Javadoc) @@ -3189,7 +3203,7 @@ class QueryCursorPreparer implements CursorPreparer { private final Query query; private final @Nullable Class type; - public QueryCursorPreparer(Query query, @Nullable Class type) { + QueryCursorPreparer(Query query, @Nullable Class type) { this.query = query; this.type = type; @@ -3331,7 +3345,6 @@ public GeoResult doWith(@Nullable Document object) { * @author Thomas Darimont * @since 1.7 */ - @AllArgsConstructor(access = AccessLevel.PACKAGE) static class CloseableIterableCursorAdapter implements CloseableIterator { private volatile @Nullable MongoCursor cursor; @@ -3345,7 +3358,7 @@ static class CloseableIterableCursorAdapter implements CloseableIterator { * @param exceptionTranslator * @param objectReadCallback */ - public CloseableIterableCursorAdapter(MongoIterable cursor, + CloseableIterableCursorAdapter(MongoIterable cursor, PersistenceExceptionTranslator exceptionTranslator, DocumentCallback objectReadCallback) { this.cursor = cursor.iterator(); @@ -3353,6 +3366,14 @@ public CloseableIterableCursorAdapter(MongoIterable cursor, this.objectReadCallback = objectReadCallback; } + CloseableIterableCursorAdapter(MongoCursor cursor, PersistenceExceptionTranslator exceptionTranslator, + DocumentCallback objectReadCallback) { + + this.cursor = cursor; + this.exceptionTranslator = exceptionTranslator; + this.objectReadCallback = objectReadCallback; + } + @Override public boolean hasNext() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java index 6afb8e9405..f84bba4c20 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import org.bson.Document; import org.springframework.data.mapping.SimplePropertyHandler; import org.springframework.data.mapping.context.MappingContext; @@ -33,11 +30,14 @@ * @author Christoph Strobl * @since 2.1 */ -@RequiredArgsConstructor(access = AccessLevel.PACKAGE) class PropertyOperations { private final MappingContext, MongoPersistentProperty> mappingContext; + PropertyOperations(MappingContext, MongoPersistentProperty> mappingContext) { + this.mappingContext = mappingContext; + } + /** * For cases where {@code fields} is {@link Document#isEmpty() empty} include only fields that are required for * creating the projection (target) type if the {@code targetType} is a {@literal DTO projection} or a diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java index ce512b2615..77c688c77f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java @@ -15,10 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; import reactor.core.publisher.Flux; import org.springframework.data.mongodb.core.aggregation.Aggregation; @@ -62,15 +58,22 @@ public ReactiveAggregation aggregateAndReturn(Class domainType) { return new ReactiveAggregationSupport<>(template, domainType, null, null); } - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ReactiveAggregationSupport implements AggregationOperationWithAggregation, ReactiveAggregation, TerminatingAggregationOperation { - @NonNull ReactiveMongoTemplate template; - @NonNull Class domainType; - Aggregation aggregation; - String collection; + private final ReactiveMongoTemplate template; + private final Class domainType; + private final Aggregation aggregation; + private final String collection; + + ReactiveAggregationSupport(ReactiveMongoTemplate template, Class domainType, Aggregation aggregation, + String collection) { + + this.template = template; + this.domainType = domainType; + this.aggregation = aggregation; + this.collection = collection; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java index b05204a7eb..37aa0d38f0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java @@ -15,15 +15,10 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.bson.Document; - import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; @@ -39,12 +34,15 @@ * @author Christoph Strobl * @since 2.0 */ -@RequiredArgsConstructor class ReactiveFindOperationSupport implements ReactiveFindOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull ReactiveMongoTemplate template; + private final ReactiveMongoTemplate template; + + ReactiveFindOperationSupport(ReactiveMongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -64,16 +62,24 @@ public ReactiveFind query(Class domainType) { * @author Christoph Strobl * @since 2.0 */ - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ReactiveFindSupport implements ReactiveFind, FindWithCollection, FindWithProjection, FindWithQuery { - @NonNull ReactiveMongoTemplate template; - @NonNull Class domainType; - Class returnType; - String collection; - Query query; + private final ReactiveMongoTemplate template; + private final Class domainType; + private final Class returnType; + private final String collection; + private final Query query; + + ReactiveFindSupport(ReactiveMongoTemplate template, Class domainType, Class returnType, + String collection, Query query) { + + this.template = template; + this.domainType = domainType; + this.returnType = returnType; + this.collection = collection; + this.query = query; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java index e0fc029bb6..bc7eab0cc5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java @@ -15,10 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -34,10 +30,13 @@ * @author Christoph Strobl * @since 2.0 */ -@RequiredArgsConstructor class ReactiveInsertOperationSupport implements ReactiveInsertOperation { - private final @NonNull ReactiveMongoTemplate template; + private final ReactiveMongoTemplate template; + + ReactiveInsertOperationSupport(ReactiveMongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -51,13 +50,18 @@ public ReactiveInsert insert(Class domainType) { return new ReactiveInsertSupport<>(template, domainType, null); } - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ReactiveInsertSupport implements ReactiveInsert { - @NonNull ReactiveMongoTemplate template; - @NonNull Class domainType; - String collection; + private final ReactiveMongoTemplate template; + private final Class domainType; + private final String collection; + + ReactiveInsertSupport(ReactiveMongoTemplate template, Class domainType, String collection) { + + this.template = template; + this.domainType = domainType; + this.collection = collection; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java index 4f9d5669fc..e76417bebe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; @@ -31,12 +29,15 @@ * @author Christoph Strobl * @since 2.1 */ -@RequiredArgsConstructor class ReactiveMapReduceOperationSupport implements ReactiveMapReduceOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull ReactiveMongoTemplate template; + private final ReactiveMongoTemplate template; + + ReactiveMapReduceOperationSupport(ReactiveMongoTemplate template) { + this.template = template; + } /* * (non-Javascript) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 9bfcc533f7..5abf54a2e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,9 +17,6 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -2410,8 +2407,8 @@ protected Flux doFind(String collectionName, Document query, Document fie * @param query the query document that specifies the criteria used to find a record. * @param fields the document that specifies the fields to be returned. * @param entityClass the parameterized type of the returned list. - * @param preparer allows for customization of the {@link com.mongodb.client.FindIterable} used when iterating over the result set, (apply - * limits, skips and so on). + * @param preparer allows for customization of the {@link com.mongodb.client.FindIterable} used when iterating over + * the result set, (apply limits, skips and so on). * @return the {@link List} of converted objects. */ protected Flux doFind(String collectionName, Document query, Document fields, Class entityClass, @@ -2885,7 +2882,6 @@ public Publisher doInCollection(MongoCollection collection) * * @author Mark Paluch */ - @RequiredArgsConstructor private static class FindCallback implements ReactiveCollectionQueryCallback { private final @Nullable Document query; @@ -2895,6 +2891,12 @@ private static class FindCallback implements ReactiveCollectionQueryCallback doInCollection(MongoCollection collection) { @@ -2948,7 +2950,6 @@ public Publisher doInCollection(MongoCollection collection) /** * @author Mark Paluch */ - @RequiredArgsConstructor private static class FindAndModifyCallback implements ReactiveCollectionCallback { private final Document query; @@ -2958,6 +2959,17 @@ private static class FindAndModifyCallback implements ReactiveCollectionCallback private final List arrayFilters; private final FindAndModifyOptions options; + FindAndModifyCallback(Document query, Document fields, Document sort, Object update, List arrayFilters, + FindAndModifyOptions options) { + + this.query = query; + this.fields = fields; + this.sort = sort; + this.update = update; + this.arrayFilters = arrayFilters; + this.options = options; + } + @Override public Publisher doInCollection(MongoCollection collection) throws MongoException, DataAccessException { @@ -3013,7 +3025,6 @@ private static FindOneAndUpdateOptions convertToFindOneAndUpdateOptions(FindAndM * @author Christoph Strobl * @since 2.1 */ - @RequiredArgsConstructor(access = AccessLevel.PACKAGE) private static class FindAndReplaceCallback implements ReactiveCollectionCallback { private final Document query; @@ -3023,6 +3034,17 @@ private static class FindAndReplaceCallback implements ReactiveCollectionCallbac private final @Nullable com.mongodb.client.model.Collation collation; private final FindAndReplaceOptions options; + FindAndReplaceCallback(Document query, Document fields, Document sort, Document update, + com.mongodb.client.model.Collation collation, FindAndReplaceOptions options) { + + this.query = query; + this.fields = fields; + this.sort = sort; + this.update = update; + this.collation = collation; + this.options = options; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.ReactiveCollectionCallback#doInCollection(com.mongodb.reactivestreams.client.MongoCollection) @@ -3139,13 +3161,20 @@ public Mono doWith(Document document) { * @author Roman Puchkovskiy * @since 2.0 */ - @RequiredArgsConstructor private class ProjectingReadCallback implements DocumentCallback { - private final @NonNull EntityReader reader; - private final @NonNull Class entityType; - private final @NonNull Class targetType; - private final @NonNull String collectionName; + private final EntityReader reader; + private final Class entityType; + private final Class targetType; + private final String collectionName; + + ProjectingReadCallback(EntityReader reader, Class entityType, Class targetType, + String collectionName) { + this.reader = reader; + this.entityType = entityType; + this.targetType = targetType; + this.collectionName = collectionName; + } @SuppressWarnings("unchecked") public Mono doWith(Document document) { @@ -3365,11 +3394,14 @@ public Mono getMongoDatabase() { } } - @RequiredArgsConstructor class IndexCreatorEventListener implements ApplicationListener> { final Consumer subscriptionExceptionHandler; + public IndexCreatorEventListener(Consumer subscriptionExceptionHandler) { + this.subscriptionExceptionHandler = subscriptionExceptionHandler; + } + @Override public void onApplicationEvent(MappingContextEvent event) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java index 62835c0231..98ef34a784 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java @@ -15,10 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -35,12 +31,15 @@ * @author Christoph Strobl * @since 2.0 */ -@RequiredArgsConstructor class ReactiveRemoveOperationSupport implements ReactiveRemoveOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull ReactiveMongoTemplate tempate; + private final ReactiveMongoTemplate tempate; + + ReactiveRemoveOperationSupport(ReactiveMongoTemplate tempate) { + this.tempate = tempate; + } /* * (non-Javadoc) @@ -54,14 +53,20 @@ public ReactiveRemove remove(Class domainType) { return new ReactiveRemoveSupport<>(tempate, domainType, ALL_QUERY, null); } - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ReactiveRemoveSupport implements ReactiveRemove, RemoveWithCollection { - @NonNull ReactiveMongoTemplate template; - @NonNull Class domainType; - Query query; - String collection; + private final ReactiveMongoTemplate template; + private final Class domainType; + private final Query query; + private final String collection; + + ReactiveRemoveSupport(ReactiveMongoTemplate template, Class domainType, Query query, String collection) { + + this.template = template; + this.domainType = domainType; + this.query = query; + this.collection = collection; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java index ff1aede220..d723e1e337 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java @@ -15,13 +15,10 @@ */ package org.springframework.data.mongodb.core; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.FieldDefaults; import reactor.core.publisher.Mono; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -35,12 +32,15 @@ * @author Christoph Strobl * @since 2.0 */ -@RequiredArgsConstructor class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation { private static final Query ALL_QUERY = new Query(); - private final @NonNull ReactiveMongoTemplate template; + private final ReactiveMongoTemplate template; + + ReactiveUpdateOperationSupport(ReactiveMongoTemplate template) { + this.template = template; + } /* * (non-Javadoc) @@ -54,21 +54,34 @@ public ReactiveUpdate update(Class domainType) { return new ReactiveUpdateSupport<>(template, domainType, ALL_QUERY, null, null, null, null, null, domainType); } - @RequiredArgsConstructor - @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) static class ReactiveUpdateSupport implements ReactiveUpdate, UpdateWithCollection, UpdateWithQuery, TerminatingUpdate, FindAndReplaceWithOptions, FindAndReplaceWithProjection, TerminatingFindAndReplace { - @NonNull ReactiveMongoTemplate template; - @NonNull Class domainType; - Query query; - org.springframework.data.mongodb.core.query.UpdateDefinition update; - @Nullable String collection; - @Nullable FindAndModifyOptions findAndModifyOptions; - @Nullable FindAndReplaceOptions findAndReplaceOptions; - @Nullable Object replacement; - @NonNull Class targetType; + private final ReactiveMongoTemplate template; + private final Class domainType; + private final Query query; + private final org.springframework.data.mongodb.core.query.UpdateDefinition update; + @Nullable private final String collection; + @Nullable private final FindAndModifyOptions findAndModifyOptions; + @Nullable private final FindAndReplaceOptions findAndReplaceOptions; + @Nullable private final Object replacement; + private final Class targetType; + + ReactiveUpdateSupport(ReactiveMongoTemplate template, Class domainType, Query query, UpdateDefinition update, + String collection, FindAndModifyOptions findAndModifyOptions, FindAndReplaceOptions findAndReplaceOptions, + Object replacement, Class targetType) { + + this.template = template; + this.domainType = domainType; + this.query = query; + this.update = update; + this.collection = collection; + this.findAndModifyOptions = findAndModifyOptions; + this.findAndReplaceOptions = findAndReplaceOptions; + this.replacement = replacement; + this.targetType = targetType; + } /* * (non-Javadoc) @@ -123,7 +136,9 @@ public Mono findAndModify() { String collectionName = getCollectionName(); - return template.findAndModify(query, update, findAndModifyOptions != null ? findAndModifyOptions : FindAndModifyOptions.none(), targetType, collectionName); + return template.findAndModify(query, update, + findAndModifyOptions != null ? findAndModifyOptions : FindAndModifyOptions.none(), targetType, + collectionName); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java index 4eedce82a2..603e8d027b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.core; -import lombok.Value; import reactor.core.publisher.Mono; import org.bson.codecs.configuration.CodecRegistry; @@ -27,6 +26,7 @@ import org.springframework.data.mongodb.SessionAwareMethodInterceptor; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import com.mongodb.ClientSessionOptions; import com.mongodb.ConnectionString; @@ -175,11 +175,16 @@ public ReactiveMongoDatabaseFactory withSession(ClientSession session) { * @author Christoph Strobl * @since 2.1 */ - @Value - static class ClientSessionBoundMongoDbFactory implements ReactiveMongoDatabaseFactory { + static final class ClientSessionBoundMongoDbFactory implements ReactiveMongoDatabaseFactory { - ClientSession session; - ReactiveMongoDatabaseFactory delegate; + private final ClientSession session; + private final ReactiveMongoDatabaseFactory delegate; + + ClientSessionBoundMongoDbFactory(ClientSession session, ReactiveMongoDatabaseFactory delegate) { + + this.session = session; + this.delegate = delegate; + } /* * (non-Javadoc) @@ -268,5 +273,40 @@ private T createProxyInstance(com.mongodb.session.ClientSession session, T t return targetType.cast(factory.getProxy()); } + + public ClientSession getSession() { + return this.session; + } + + public ReactiveMongoDatabaseFactory getDelegate() { + return this.delegate; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ClientSessionBoundMongoDbFactory that = (ClientSessionBoundMongoDbFactory) o; + + if (!ObjectUtils.nullSafeEquals(this.session, that.session)) { + return false; + } + return ObjectUtils.nullSafeEquals(this.delegate, that.delegate); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(this.session); + result = 31 * result + ObjectUtils.nullSafeHashCode(this.delegate); + return result; + } + + public String toString() { + return "SimpleReactiveMongoDatabaseFactory.ClientSessionBoundMongoDbFactory(session=" + this.getSession() + + ", delegate=" + this.getDelegate() + ")"; + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index fcaf105678..ac5d22413f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -15,10 +15,6 @@ */ package org.springframework.data.mongodb.core.index; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -33,7 +29,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.domain.Sort; import org.springframework.data.mapping.Association; @@ -733,8 +728,6 @@ private String createMapKey(MongoPersistentProperty property) { * @author Christoph Strobl * @author Mark Paluch */ - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - @EqualsAndHashCode static class Path { private static final Path EMPTY = new Path(Collections.emptyList(), false); @@ -742,6 +735,11 @@ static class Path { private final List> elements; private final boolean cycle; + private Path(List> elements, boolean cycle) { + this.elements = elements; + this.cycle = cycle; + } + /** * @return an empty {@link Path}. * @since 1.10.8 @@ -843,6 +841,28 @@ private static String toPath(Iterator> iterator) { return builder.toString(); } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Path that = (Path) o; + + if (this.cycle != that.cycle) { + return false; + } + return ObjectUtils.nullSafeEquals(this.elements, that.elements); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(elements); + result = 31 * result + (cycle ? 1 : 0); + return result; + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java index 7cc656d54f..66cdf7a80a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java @@ -16,14 +16,8 @@ package org.springframework.data.mongodb.core.index; import org.bson.Document; - -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.data.mongodb.core.query.CriteriaDefinition; - -import com.mongodb.DBObject; +import org.springframework.util.Assert; /** * {@link IndexFilter} implementation for usage with plain {@link Document} as well as {@link CriteriaDefinition} filter @@ -32,10 +26,16 @@ * @author Christoph Strobl * @since 1.10 */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) public class PartialIndexFilter implements IndexFilter { - private final @NonNull Object filterExpression; + private final Object filterExpression; + + private PartialIndexFilter(Object filterExpression) { + + Assert.notNull(filterExpression, "FilterExpression must not be null!"); + + this.filterExpression = filterExpression; + } /** * Create new {@link PartialIndexFilter} for given {@link Document filter expression}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java index 81b67c2109..668316f2a0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core.messaging; -import lombok.AllArgsConstructor; - import java.time.Instant; import java.util.Arrays; import java.util.Collections; @@ -217,12 +215,17 @@ MongoNamespace createNamespaceFromOptions(RequestOptions options) { * * @since 2.1 */ - @AllArgsConstructor static class ChangeStreamEventMessage implements Message, T> { private final ChangeStreamEvent delegate; private final MessageProperties messageProperties; + ChangeStreamEventMessage(ChangeStreamEvent delegate, MessageProperties messageProperties) { + + this.delegate = delegate; + this.messageProperties = messageProperties; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.messaging.Message#getRaw() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java index c9f367614a..db84b553b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java @@ -15,10 +15,6 @@ */ package org.springframework.data.mongodb.core.messaging; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import java.time.Duration; import java.util.LinkedHashMap; import java.util.Map; @@ -34,6 +30,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ErrorHandler; +import org.springframework.util.ObjectUtils; /** * Simple {@link Executor} based {@link MessageListenerContainer} implementation for running {@link Task tasks} like @@ -259,7 +256,6 @@ public void remove(Subscription subscription) { * @author Christoph Strobl * @since 2.1 */ - @EqualsAndHashCode static class TaskSubscription implements Subscription { private final Task task; @@ -286,19 +282,39 @@ public boolean await(Duration timeout) throws InterruptedException { public void cancel() throws DataAccessResourceFailureException { task.cancel(); } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + TaskSubscription that = (TaskSubscription) o; + + return ObjectUtils.nullSafeEquals(this.task, that.task); + } + + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(task); + } } /** * @author Christoph Strobl * @since 2.1 */ - @RequiredArgsConstructor(access = AccessLevel.PACKAGE) private static class DecoratingLoggingErrorHandler implements ErrorHandler { private final Log logger = LogFactory.getLog(DecoratingLoggingErrorHandler.class); private final ErrorHandler delegate; + DecoratingLoggingErrorHandler(ErrorHandler delegate) { + this.delegate = delegate; + } + @Override public void handleError(Throwable t) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java index bdcddad854..50c47a679f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core.messaging; -import lombok.ToString; - import org.bson.Document; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.util.ClassUtils; @@ -26,7 +24,6 @@ * @author Mark Paluch * @since 2.1 */ -@ToString(of = { "delegate", "targetType" }) class LazyMappingDelegatingMessage implements Message { private final Message delegate; @@ -82,4 +79,8 @@ public T getBody() { public MessageProperties getProperties() { return delegate.getProperties(); } + + public String toString() { + return "LazyMappingDelegatingMessage(delegate=" + this.delegate + ", targetType=" + this.targetType + ")"; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java index 13b27f9007..2024d0b527 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java @@ -15,11 +15,9 @@ */ package org.springframework.data.mongodb.core.messaging; -import lombok.EqualsAndHashCode; -import lombok.ToString; - import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * General message abstraction for any type of Event / Message published by MongoDB server to the client. This might be @@ -65,8 +63,6 @@ public interface Message { * @author Christoph Strobl * @since 2.1 */ - @ToString - @EqualsAndHashCode class MessageProperties { private static final MessageProperties EMPTY = new MessageProperties(); @@ -111,6 +107,34 @@ public static MessagePropertiesBuilder builder() { return new MessagePropertiesBuilder(); } + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + MessageProperties that = (MessageProperties) o; + + if (!ObjectUtils.nullSafeEquals(this.databaseName, that.databaseName)) { + return false; + } + + return ObjectUtils.nullSafeEquals(this.collectionName, that.collectionName); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(databaseName); + result = 31 * result + ObjectUtils.nullSafeHashCode(collectionName); + return result; + } + + public String toString() { + return "Message.MessageProperties(databaseName=" + this.getDatabaseName() + ", collectionName=" + + this.getCollectionName() + ")"; + } + /** * Builder for {@link MessageProperties}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java index 320ba5ec6a..1907e4442c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java @@ -15,11 +15,9 @@ */ package org.springframework.data.mongodb.core.messaging; -import lombok.EqualsAndHashCode; -import lombok.ToString; - import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Trivial {@link Message} implementation. @@ -27,8 +25,6 @@ * @author Christoph Strobl * @since 2.1 */ -@EqualsAndHashCode -@ToString class SimpleMessage implements Message { private @Nullable final S raw; @@ -75,4 +71,35 @@ public T getBody() { public MessageProperties getProperties() { return properties; } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + SimpleMessage that = (SimpleMessage) o; + + if (!ObjectUtils.nullSafeEquals(this.raw, that.raw)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(this.body, that.body)) { + return false; + } + return ObjectUtils.nullSafeEquals(this.properties, that.properties); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(raw); + result = 31 * result + ObjectUtils.nullSafeHashCode(body); + result = 31 * result + ObjectUtils.nullSafeHashCode(properties); + return result; + } + + public String toString() { + return "SimpleMessage(raw=" + this.getRaw() + ", body=" + this.getBody() + ", properties=" + this.getProperties() + + ")"; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java index 80428ddf60..191ba34ccf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java @@ -15,11 +15,6 @@ */ package org.springframework.data.mongodb.core.query; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - import java.util.Locale; import java.util.Optional; @@ -515,8 +510,6 @@ default Optional getCaseLevel() { * * @since 2.0 */ - @AllArgsConstructor(access = AccessLevel.PACKAGE) - @Getter static class ICUComparisonLevel implements ComparisonLevel { private final int level; @@ -526,6 +519,24 @@ static class ICUComparisonLevel implements ComparisonLevel { ICUComparisonLevel(int level) { this(level, Optional.empty(), Optional.empty()); } + + ICUComparisonLevel(int level, Optional caseFirst, Optional caseLevel) { + this.level = level; + this.caseFirst = caseFirst; + this.caseLevel = caseLevel; + } + + public int getLevel() { + return this.level; + } + + public Optional getCaseFirst() { + return this.caseFirst; + } + + public Optional getCaseLevel() { + return this.caseLevel; + } } /** @@ -650,7 +661,6 @@ public ComparisonLevel caseFirst(CaseFirst caseFirst) { /** * @since 2.0 */ - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public static class CaseFirst { private static final CaseFirst UPPER = new CaseFirst("upper"); @@ -659,6 +669,10 @@ public static class CaseFirst { private final String state; + private CaseFirst(String state) { + this.state = state; + } + /** * Sort uppercase before lowercase. * @@ -690,7 +704,6 @@ public static CaseFirst off() { /** * @since 2.0 */ - @RequiredArgsConstructor(access = AccessLevel.PACKAGE) public static class Alternate { private static final Alternate NON_IGNORABLE = new Alternate("non-ignorable", Optional.empty()); @@ -698,6 +711,11 @@ public static class Alternate { final String alternate; final Optional maxVariable; + Alternate(String alternate, Optional maxVariable) { + this.alternate = alternate; + this.maxVariable = maxVariable; + } + /** * Consider Whitespace and punctuation as base characters. * @@ -761,12 +779,17 @@ public Alternate space() { * @see ICU - International Components for Unicode * @since 2.0 */ - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public static class CollationLocale { private final String language; private final Optional variant; + private CollationLocale(String language, Optional variant) { + + this.language = language; + this.variant = variant; + } + /** * Create new {@link CollationLocale} for given language. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java index 35b7714968..4940a857e9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.core.query; -import lombok.EqualsAndHashCode; - import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -24,6 +22,7 @@ import org.bson.Document; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * @author Thomas Risberg @@ -32,7 +31,6 @@ * @author Christoph Strobl * @author Mark Paluch */ -@EqualsAndHashCode public class Field { private final Map criteria = new HashMap(); @@ -103,4 +101,40 @@ public Document getFieldsObject() { return document; } + + @Override + public boolean equals(Object o) { + + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Field field = (Field) o; + + if (positionValue != field.positionValue) { + return false; + } + if (!ObjectUtils.nullSafeEquals(criteria, field.criteria)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(slices, field.slices)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(elemMatchs, field.elemMatchs)) { + return false; + } + return ObjectUtils.nullSafeEquals(positionKey, field.positionKey); + } + + @Override + public int hashCode() { + + int result = ObjectUtils.nullSafeHashCode(criteria); + result = 31 * result + ObjectUtils.nullSafeHashCode(slices); + result = 31 * result + ObjectUtils.nullSafeHashCode(elemMatchs); + result = 31 * result + ObjectUtils.nullSafeHashCode(positionKey); + result = 31 * result + positionValue; + return result; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java index 5701b276de..e75b194061 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java @@ -15,14 +15,10 @@ */ package org.springframework.data.mongodb.core.query; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.Set; import org.springframework.data.domain.ExampleMatcher; +import org.springframework.util.ObjectUtils; /** * {@link ExampleMatcher} implementation for query by example (QBE). Unlike plain {@link ExampleMatcher} this untyped @@ -33,11 +29,13 @@ * @author Mark Paluch * @since 2.0 */ -@EqualsAndHashCode -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) public class UntypedExampleMatcher implements ExampleMatcher { - private final @NonNull ExampleMatcher delegate; + private final ExampleMatcher delegate; + + private UntypedExampleMatcher(ExampleMatcher delegate) { + this.delegate = delegate; + } /* * (non-Javadoc) @@ -224,4 +222,22 @@ public MatchMode getMatchMode() { return delegate.getMatchMode(); } + @Override + public boolean equals(Object o) { + + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + UntypedExampleMatcher that = (UntypedExampleMatcher) o; + + return ObjectUtils.nullSafeEquals(delegate, that.delegate); + } + + @Override + public int hashCode() { + + return ObjectUtils.nullSafeHashCode(delegate); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java index cff333b766..1c736fcda0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java @@ -15,10 +15,8 @@ */ package org.springframework.data.mongodb.core.schema; -import lombok.AllArgsConstructor; -import lombok.NonNull; - import org.bson.Document; +import org.springframework.util.Assert; /** * Value object representing a MongoDB-specific JSON schema which is the default {@link MongoJsonSchema} implementation. @@ -27,10 +25,15 @@ * @author Mark Paluch * @since 2.1 */ -@AllArgsConstructor class DefaultMongoJsonSchema implements MongoJsonSchema { - private final @NonNull JsonSchemaObject root; + private final JsonSchemaObject root; + + DefaultMongoJsonSchema(JsonSchemaObject root) { + + Assert.notNull(root, "Root must not be null!"); + this.root = root; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java index 18aa0b355b..15a9c5aa10 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java @@ -15,10 +15,8 @@ */ package org.springframework.data.mongodb.core.schema; -import lombok.AllArgsConstructor; -import lombok.NonNull; - import org.bson.Document; +import org.springframework.util.Assert; /** * JSON schema backed by a {@link org.bson.Document} object. @@ -26,10 +24,15 @@ * @author Mark Paluch * @since 2.1 */ -@AllArgsConstructor class DocumentJsonSchema implements MongoJsonSchema { - private final @NonNull Document document; + private final Document document; + + DocumentJsonSchema(Document document) { + + Assert.notNull(document, "Document must not be null!"); + this.document = document; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java index 6ea9c06497..c564979858 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core.schema; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import java.math.BigDecimal; import java.util.Arrays; import java.util.Collection; @@ -44,6 +41,7 @@ import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.TimestampJsonSchemaObject; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; /** * Interface that can be implemented by objects that know how to serialize themselves to JSON schema using @@ -500,12 +498,14 @@ default Type toBsonType() { * @author Christpoh Strobl * @since 2.1 */ - @RequiredArgsConstructor - @EqualsAndHashCode class JsonType implements Type { private final String name; + public JsonType(String name) { + this.name = name; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type#representation() @@ -523,18 +523,37 @@ public String representation() { public String value() { return name; } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + JsonType jsonType = (JsonType) o; + + return ObjectUtils.nullSafeEquals(name, jsonType.name); + } + + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(name); + } } /** * @author Christpoh Strobl * @since 2.1 */ - @RequiredArgsConstructor - @EqualsAndHashCode class BsonType implements Type { private final String name; + BsonType(String name) { + this.name = name; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type#representation() @@ -552,6 +571,24 @@ public String representation() { public String value() { return name; } + + @Override + public boolean equals(Object o) { + + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + BsonType bsonType = (BsonType) o; + + return ObjectUtils.nullSafeEquals(name, bsonType.name); + } + + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(name); + } } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java index 3d3c2f459a..68f0f94c47 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core.schema; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.NumericJsonSchemaObject; import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.ObjectJsonSchemaObject; import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.*; @@ -239,11 +236,14 @@ static JsonSchemaProperty required(JsonSchemaProperty property) { /** * Builder for {@link IdentifiableJsonSchemaProperty}. */ - @RequiredArgsConstructor(access = AccessLevel.PACKAGE) class JsonSchemaPropertyBuilder { private final String identifier; + JsonSchemaPropertyBuilder(String identifier) { + this.identifier = identifier; + } + /** * Configure a {@link Type} for the property. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java index d1f695428a..ea475ef72d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.core.schema; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import java.util.Collection; import java.util.Collections; import java.util.List; @@ -182,7 +179,6 @@ protected String generateDescription() { * @author Christoph Strobl * @since 2.1 */ - @RequiredArgsConstructor(access = AccessLevel.PACKAGE) static class Restrictions { private final Collection possibleValues; @@ -191,6 +187,16 @@ static class Restrictions { private final Collection oneOf; private final @Nullable JsonSchemaObject notMatch; + Restrictions(Collection possibleValues, Collection allOf, + Collection anyOf, Collection oneOf, JsonSchemaObject notMatch) { + + this.possibleValues = possibleValues; + this.allOf = allOf; + this.anyOf = anyOf; + this.oneOf = oneOf; + this.notMatch = notMatch; + } + /** * @return new empty {@link Restrictions}. */ 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 index fa76e1d473..6e20aae77e 100644 --- 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 @@ -15,15 +15,12 @@ */ package org.springframework.data.mongodb.core.validation; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import org.bson.Document; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.data.mongodb.core.query.SerializationUtils; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * {@link Validator} implementation based on {@link CriteriaDefinition query expressions}. @@ -34,12 +31,14 @@ * @see Criteria * @see Schema Validation */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -@EqualsAndHashCode class CriteriaValidator implements Validator { private final CriteriaDefinition criteria; + private CriteriaValidator(CriteriaDefinition criteria) { + this.criteria = criteria; + } + /** * Creates a new {@link Validator} object, which is basically setup of query operators, based on a * {@link CriteriaDefinition} instance. @@ -72,4 +71,21 @@ public Document toDocument() { public String toString() { return SerializationUtils.serializeToJsonSafely(toDocument()); } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + CriteriaValidator that = (CriteriaValidator) o; + + return ObjectUtils.nullSafeEquals(criteria, that.criteria); + } + + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(criteria); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java index aff1920291..74f75b3e33 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java @@ -15,13 +15,10 @@ */ package org.springframework.data.mongodb.core.validation; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import org.bson.Document; import org.springframework.data.mongodb.core.query.SerializationUtils; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Most trivial {@link Validator} implementation using plain {@link Document} to describe the desired document structure @@ -32,12 +29,14 @@ * @since 2.1 * @see Schema Validation */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -@EqualsAndHashCode class DocumentValidator implements Validator { private final Document validatorObject; + private DocumentValidator(Document validatorObject) { + this.validatorObject = validatorObject; + } + /** * Create new {@link DocumentValidator} defining validation rules via a plain {@link Document}. * @@ -68,4 +67,22 @@ public Document toDocument() { public String toString() { return SerializationUtils.serializeToJsonSafely(validatorObject); } + + @Override + public boolean equals(Object o) { + + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + DocumentValidator that = (DocumentValidator) o; + + return ObjectUtils.nullSafeEquals(validatorObject, that.validatorObject); + } + + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(validatorObject); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java index 80bb6de707..01f766892a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java @@ -15,14 +15,11 @@ */ package org.springframework.data.mongodb.core.validation; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import org.bson.Document; import org.springframework.data.mongodb.core.query.SerializationUtils; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * {@link Validator} implementation based on {@link MongoJsonSchema JSON Schema}. @@ -32,12 +29,14 @@ * @since 2.1 * @see Schema Validation */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -@EqualsAndHashCode class JsonSchemaValidator implements Validator { private final MongoJsonSchema schema; + private JsonSchemaValidator(MongoJsonSchema schema) { + this.schema = schema; + } + /** * Create new {@link JsonSchemaValidator} defining validation rules via {@link MongoJsonSchema}. * @@ -68,4 +67,22 @@ public Document toDocument() { public String toString() { return SerializationUtils.serializeToJsonSafely(toDocument()); } + + @Override + public boolean equals(Object o) { + + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + JsonSchemaValidator that = (JsonSchemaValidator) o; + + return ObjectUtils.nullSafeEquals(schema, that.schema); + } + + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(schema); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index e78cb6504a..970fcbbdbe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.repository.query; -import lombok.experimental.UtilityClass; - import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -49,11 +47,14 @@ * @author Mark Paluch * @since 2.2 */ -@UtilityClass -class AggregationUtils { +final class AggregationUtils { private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); + private AggregationUtils() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + /** * Apply a collation extracted from the given {@literal collationExpression} to the given * {@link org.springframework.data.mongodb.core.aggregation.AggregationOptions.Builder}. Potentially replace parameter diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java index e07a85e1d6..b2e660ab7d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java @@ -15,16 +15,17 @@ */ package org.springframework.data.mongodb.repository.query; -import lombok.experimental.UtilityClass; - /** * Utility class containing methods to interact with boolean values. * * @author Mark Paluch * @since 2.0.9 */ -@UtilityClass -class BooleanUtil { +final class BooleanUtil { + + private BooleanUtil() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } /** * Count the number of {@literal true} values. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index 411674e269..7302f30567 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.repository.query; -import lombok.experimental.UtilityClass; - import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,12 +37,15 @@ * @author Christoph Strobl * @since 2.2 */ -@UtilityClass -class CollationUtils { +final class CollationUtils { private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)"); + private CollationUtils() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + /** * Compute the {@link Collation} by inspecting the {@link ConvertingParameterAccessor#getCollation() parameter * accessor} or parsing a potentially given {@literal collationExpression}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index 3b5db06913..facc461f5f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -15,9 +15,6 @@ */ package org.springframework.data.mongodb.repository.query; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.List; import org.springframework.data.domain.Page; @@ -30,6 +27,7 @@ import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Point; +import org.springframework.data.mongodb.core.ExecutableFindOperation; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; import org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind; import org.springframework.data.mongodb.core.MongoOperations; @@ -37,6 +35,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.repository.support.PageableExecutionUtils; import org.springframework.data.util.TypeInformation; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import com.mongodb.client.result.DeleteResult; @@ -62,11 +61,19 @@ interface MongoQueryExecution { * @author Christoph Strobl * @since 1.5 */ - @RequiredArgsConstructor final class SlicedExecution implements MongoQueryExecution { - private final @NonNull FindWithQuery find; - private final @NonNull Pageable pageable; + private final FindWithQuery find; + private final Pageable pageable; + + public SlicedExecution(ExecutableFindOperation.FindWithQuery find, Pageable pageable) { + + Assert.notNull(find, "Find must not be null!"); + Assert.notNull(pageable, "Pageable must not be null!"); + + this.find = find; + this.pageable = pageable; + } /* * (non-Javadoc) @@ -95,11 +102,19 @@ public Object execute(Query query) { * @author Mark Paluch * @author Christoph Strobl */ - @RequiredArgsConstructor final class PagedExecution implements MongoQueryExecution { - private final @NonNull FindWithQuery operation; - private final @NonNull Pageable pageable; + private final FindWithQuery operation; + private final Pageable pageable; + + public PagedExecution(ExecutableFindOperation.FindWithQuery operation, Pageable pageable) { + + Assert.notNull(operation, "Operation must not be null!"); + Assert.notNull(pageable, "Pageable must not be null!"); + + this.operation = operation; + this.pageable = pageable; + } /* * (non-Javadoc) @@ -133,12 +148,23 @@ public Object execute(Query query) { * * @author Oliver Gierke */ - @RequiredArgsConstructor class GeoNearExecution implements MongoQueryExecution { - private final @NonNull FindWithQuery operation; - private final @NonNull MongoQueryMethod method; - private final @NonNull MongoParameterAccessor accessor; + private final FindWithQuery operation; + private final MongoQueryMethod method; + private final MongoParameterAccessor accessor; + + public GeoNearExecution(ExecutableFindOperation.FindWithQuery operation, MongoQueryMethod method, + MongoParameterAccessor accessor) { + + Assert.notNull(operation, "Operation must not be null!"); + Assert.notNull(method, "Method must not be null!"); + Assert.notNull(accessor, "Accessor must not be null!"); + + this.operation = operation; + this.method = method; + this.accessor = accessor; + } /* * (non-Javadoc) @@ -236,11 +262,19 @@ public Object execute(Query query) { * @author Christoph Strobl * @since 1.5 */ - @RequiredArgsConstructor final class DeleteExecution implements MongoQueryExecution { - private final @NonNull MongoOperations operations; - private final @NonNull MongoQueryMethod method; + private final MongoOperations operations; + private final MongoQueryMethod method; + + public DeleteExecution(MongoOperations operations, MongoQueryMethod method) { + + Assert.notNull(operations, "Operations must not be null!"); + Assert.notNull(method, "Method must not be null!"); + + this.operations = operations; + this.method = method; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 9feb4a9d96..e2b9d51da0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -15,13 +15,10 @@ */ package org.springframework.data.mongodb.repository.query; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.reactivestreams.Publisher; - import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Range; @@ -37,6 +34,7 @@ import org.springframework.data.repository.util.ReactiveWrappers; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** @@ -57,13 +55,20 @@ interface ReactiveMongoQueryExecution { * * @author Mark Paluch */ - @RequiredArgsConstructor class GeoNearExecution implements ReactiveMongoQueryExecution { private final ReactiveMongoOperations operations; private final MongoParameterAccessor accessor; private final TypeInformation returnType; + public GeoNearExecution(ReactiveMongoOperations operations, MongoParameterAccessor accessor, + TypeInformation returnType) { + + this.operations = operations; + this.accessor = accessor; + this.returnType = returnType; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) @@ -112,12 +117,16 @@ private boolean isStreamOfGeoResult() { * @author Mark Paluch * @author Artyom Gabeev */ - @RequiredArgsConstructor final class DeleteExecution implements ReactiveMongoQueryExecution { private final ReactiveMongoOperations operations; private final MongoQueryMethod method; + public DeleteExecution(ReactiveMongoOperations operations, MongoQueryMethod method) { + this.operations = operations; + this.method = method; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) @@ -142,11 +151,19 @@ public Object execute(Query query, Class type, String collection) { * An {@link ReactiveMongoQueryExecution} that wraps the results of the given delegate with the given result * processing. */ - @RequiredArgsConstructor final class ResultProcessingExecution implements ReactiveMongoQueryExecution { - private final @NonNull ReactiveMongoQueryExecution delegate; - private final @NonNull Converter converter; + private final ReactiveMongoQueryExecution delegate; + private final Converter converter; + + public ResultProcessingExecution(ReactiveMongoQueryExecution delegate, Converter converter) { + + Assert.notNull(delegate, "Delegate must not be null!"); + Assert.notNull(converter, "Converter must not be null!"); + + this.delegate = delegate; + this.converter = converter; + } @Override public Object execute(Query query, Class type, String collection) { @@ -159,12 +176,23 @@ public Object execute(Query query, Class type, String collection) { * * @author Mark Paluch */ - @RequiredArgsConstructor final class ResultProcessingConverter implements Converter { - private final @NonNull ResultProcessor processor; - private final @NonNull ReactiveMongoOperations operations; - private final @NonNull EntityInstantiators instantiators; + private final ResultProcessor processor; + private final ReactiveMongoOperations operations; + private final EntityInstantiators instantiators; + + public ResultProcessingConverter(ResultProcessor processor, ReactiveMongoOperations operations, + EntityInstantiators instantiators) { + + Assert.notNull(processor, "Processor must not be null!"); + Assert.notNull(operations, "Operations must not be null!"); + Assert.notNull(instantiators, "Instantiators must not be null!"); + + this.processor = processor; + this.operations = operations; + this.instantiators = instantiators; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java index 09a5892e53..48d35a1041 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java @@ -15,8 +15,6 @@ */ package org.springframework.data.mongodb.repository.query; -import lombok.Getter; - import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.util.Assert; @@ -28,7 +26,7 @@ class SimpleMongoEntityMetadata implements MongoEntityMetadata { private final Class type; - private final @Getter MongoPersistentEntity collectionEntity; + private final MongoPersistentEntity collectionEntity; /** * Creates a new {@link SimpleMongoEntityMetadata} using the given type and {@link MongoPersistentEntity} to use for @@ -61,4 +59,8 @@ public Class getJavaType() { public String getCollectionName() { return collectionEntity.getCollection(); } + + public MongoPersistentEntity getCollectionEntity() { + return this.collectionEntity; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java index dfbf7acbbd..d6508e8a4c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java @@ -17,9 +17,6 @@ import static org.springframework.data.querydsl.QuerydslUtils.*; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import java.io.Serializable; import java.lang.reflect.Method; import java.util.Optional; @@ -157,13 +154,21 @@ private MongoEntityInformation getEntityInformation(Class doma * @author Mark Paluch * @author Christoph Strobl */ - @RequiredArgsConstructor(access = AccessLevel.PACKAGE) private static class MongoQueryLookupStrategy implements QueryLookupStrategy { private final ReactiveMongoOperations operations; private final QueryMethodEvaluationContextProvider evaluationContextProvider; private final MappingContext, MongoPersistentProperty> mappingContext; + MongoQueryLookupStrategy(ReactiveMongoOperations operations, + QueryMethodEvaluationContextProvider evaluationContextProvider, + MappingContext, MongoPersistentProperty> mappingContext) { + + this.operations = operations; + this.evaluationContextProvider = evaluationContextProvider; + this.mappingContext = mappingContext; + } + /* * (non-Javadoc) * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 23f9ba65e0..0a1b05db3d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -17,8 +17,6 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -51,11 +49,20 @@ * @author Ruben J Garcia * @since 2.0 */ -@RequiredArgsConstructor public class SimpleReactiveMongoRepository implements ReactiveMongoRepository { - private final @NonNull MongoEntityInformation entityInformation; - private final @NonNull ReactiveMongoOperations mongoOperations; + private final MongoEntityInformation entityInformation; + private final ReactiveMongoOperations mongoOperations; + + public SimpleReactiveMongoRepository(MongoEntityInformation entityInformation, + ReactiveMongoOperations mongoOperations) { + + Assert.notNull(entityInformation, "EntityInformation must not be null!"); + Assert.notNull(mongoOperations, "MongoOperations must not be null!"); + + this.entityInformation = entityInformation; + this.mongoOperations = mongoOperations; + } /* * (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index 1402081516..2cf11d8d1b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -17,8 +17,6 @@ import static java.lang.String.*; -import lombok.Data; - import java.text.DateFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; @@ -1631,12 +1629,37 @@ private static byte[] decodeHex(final String hex) { // Spring Data Customization START - @Data static class BindableValue { - BsonType type; - Object value; - int index; + private BsonType type; + private Object value; + private int index; + + BindableValue() {} + + BsonType getType() { + return type; + } + + void setType(BsonType type) { + this.type = type; + } + + Object getValue() { + return value; + } + + void setValue(Object value) { + this.value = value; + } + + int getIndex() { + return index; + } + + void setIndex(int index) { + this.index = index; + } } // Spring Data Customization END From ce2f8a7bf5b547e21ab89059e81f9ea9566e1d7b Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 14 May 2020 11:02:06 +0200 Subject: [PATCH 0174/1381] DATAMONGO-2538 - Polishing. Reformat code. Convert utility classes to abstract ones. Original pull request: #861. --- .../data/mongodb/core/query/UntypedExampleMatcher.java | 1 - .../data/mongodb/repository/query/AggregationUtils.java | 3 +-- .../data/mongodb/repository/query/CollationUtils.java | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java index e75b194061..78101570b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java @@ -237,7 +237,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(delegate); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index 970fcbbdbe..e71306c358 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -47,12 +47,11 @@ * @author Mark Paluch * @since 2.2 */ -final class AggregationUtils { +abstract class AggregationUtils { private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); private AggregationUtils() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index 7302f30567..c77c37f65f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -37,13 +37,12 @@ * @author Christoph Strobl * @since 2.2 */ -final class CollationUtils { +abstract class CollationUtils { private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)"); private CollationUtils() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } /** From 8b50778350d62262c5dd39e3457d7453c91830d4 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 19 May 2020 11:36:37 +0200 Subject: [PATCH 0175/1381] DATAMONGO-2553 - Fix reference documentation links. Remove links to removed documentations sections. --- src/main/asciidoc/new-features.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 46f953d762..1a1fc849d9 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -87,7 +87,7 @@ * Out-of-the-box support for `java.util.Currency` in object mapping. * Support for the bulk operations introduced in MongoDB 2.6. * Upgrade to Querydsl 4. -* Assert compatibility with MongoDB 3.0 and MongoDB Java Driver 3.2 (see: <>). +* Assert compatibility with MongoDB 3.0 and MongoDB Java Driver 3.2. [[new-features.1-8-0]] == What's New in Spring Data MongoDB 1.8 @@ -101,7 +101,7 @@ [[new-features.1-7-0]] == What's New in Spring Data MongoDB 1.7 -* Assert compatibility with MongoDB 3.0 and MongoDB Java Driver 3-beta3 (see: <>). +* Assert compatibility with MongoDB 3.0 and MongoDB Java Driver 3-beta3. * Support JSR-310 and ThreeTen back-port date/time types. * Allow `Stream` as a query method return type (see: <>). * https://geojson.org/[GeoJSON] support in both domain types and queries (see: <>). From af39b422b60b9513da2b75cbf7a655ed7f466ba7 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 14 May 2020 10:51:22 +0200 Subject: [PATCH 0176/1381] DATAMONGO-2547 - Use target class ClassLoader instead of default CL when creating proxy instances. Original pull request: #865. --- .../data/mongodb/core/MongoDatabaseFactorySupport.java | 2 +- .../data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java | 2 +- .../data/mongodb/core/convert/DefaultDbRefResolver.java | 2 +- .../data/mongodb/repository/query/QueryUtils.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java index c716015eee..9762550066 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java @@ -257,7 +257,7 @@ private T createProxyInstance(com.mongodb.session.ClientSession session, T t factory.addAdvice(new SessionAwareMethodInterceptor<>(session, target, ClientSession.class, MongoDatabase.class, this::proxyDatabase, MongoCollection.class, this::proxyCollection)); - return targetType.cast(factory.getProxy()); + return targetType.cast(factory.getProxy(target.getClass().getClassLoader())); } public ClientSession getSession() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java index 603e8d027b..98c4003c5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java @@ -271,7 +271,7 @@ private T createProxyInstance(com.mongodb.session.ClientSession session, T t factory.addAdvice(new SessionAwareMethodInterceptor<>(session, target, ClientSession.class, MongoDatabase.class, this::proxyDatabase, MongoCollection.class, this::proxyCollection)); - return targetType.cast(factory.getProxy()); + return targetType.cast(factory.getProxy(target.getClass().getClassLoader())); } public ClientSession getSession() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 8e4baa5fd8..45b9e6bb75 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -202,7 +202,7 @@ private Object createLazyLoadingProxy(MongoPersistentProperty property, @Nullabl proxyFactory.addInterface(propertyType); proxyFactory.addAdvice(interceptor); - return handler.populateId(property, dbref, proxyFactory.getProxy()); + return handler.populateId(property, dbref, proxyFactory.getProxy(LazyLoadingProxy.class.getClassLoader())); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java index d08e1a87ce..b62891e3bc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java @@ -61,7 +61,7 @@ static Query decorateSort(Query query, Document defaultSort) { return combinedSort; }); - return (Query) factory.getProxy(); + return (Query) factory.getProxy(query.getClass().getClassLoader()); } /** From 3af7269dbb698d0cc57ae407bb13a37e41a6ba2b Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 13 May 2020 09:48:02 +0200 Subject: [PATCH 0177/1381] DATAMONGO-2545 - Fix regression in String query SpEL parameter binding. We reenabled parameter binding within SpEL using query parameter placeholders ?0, ?1,... instead of their array index [0],[1],... Original pull request: #864. --- .../util/json/ParameterBindingJsonReader.java | 58 ++++++++++++------- .../ParameterBindingJsonReaderUnitTests.java | 51 ++++++++++++++++ 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index 2cf11d8d1b..86e311920a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -368,26 +368,33 @@ private BindableValue bindableValueFor(JsonToken token) { if (token.getType().equals(JsonTokenType.UNQUOTED_STRING)) { - if (matcher.find()) { - - int index = computeParameterIndex(matcher.group()); - bindableValue.setValue(getBindableValueForIndex(index)); - bindableValue.setType(bsonTypeForValue(getBindableValueForIndex(index))); - return bindableValue; - } - Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(tokenValue); if (regexMatcher.find()) { String binding = regexMatcher.group(); String expression = binding.substring(3, binding.length() - 1); + Matcher inSpelMatcher = PARAMETER_BINDING_PATTERN.matcher(expression); + while (inSpelMatcher.find()) { + + int index = computeParameterIndex(inSpelMatcher.group()); + expression = expression.replace(inSpelMatcher.group(), getBindableValueForIndex(index).toString()); + } + Object value = evaluateExpression(expression); bindableValue.setValue(value); bindableValue.setType(bsonTypeForValue(value)); return bindableValue; } + if (matcher.find()) { + + int index = computeParameterIndex(matcher.group()); + bindableValue.setValue(getBindableValueForIndex(index)); + bindableValue.setType(bsonTypeForValue(getBindableValueForIndex(index))); + return bindableValue; + } + bindableValue.setValue(tokenValue); bindableValue.setType(BsonType.STRING); return bindableValue; @@ -396,26 +403,35 @@ private BindableValue bindableValueFor(JsonToken token) { String computedValue = tokenValue; - boolean matched = false; - while (matcher.find()) { - matched = true; - String group = matcher.group(); - int index = computeParameterIndex(group); - computedValue = computedValue.replace(group, nullSafeToString(getBindableValueForIndex(index))); - } - if (!matched) { + Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(computedValue); - Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(tokenValue); + while (regexMatcher.find()) { - while (regexMatcher.find()) { + String binding = regexMatcher.group(); + String expression = binding.substring(3, binding.length() - 1); - String binding = regexMatcher.group(); - String expression = binding.substring(3, binding.length() - 1); + Matcher inSpelMatcher = PARAMETER_BINDING_PATTERN.matcher(expression); + while (inSpelMatcher.find()) { - computedValue = computedValue.replace(binding, nullSafeToString(evaluateExpression(expression))); + int index = computeParameterIndex(inSpelMatcher.group()); + expression = expression.replace(inSpelMatcher.group(), getBindableValueForIndex(index).toString()); } + + computedValue = computedValue.replace(binding, nullSafeToString(evaluateExpression(expression))); + + bindableValue.setValue(computedValue); + bindableValue.setType(BsonType.STRING); + + return bindableValue; + } + + while (matcher.find()) { + + String group = matcher.group(); + int index = computeParameterIndex(group); + computedValue = computedValue.replace(group, nullSafeToString(getBindableValueForIndex(index))); } bindableValue.setValue(computedValue); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index c3257b5f71..6e6e14dbda 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -26,6 +26,7 @@ import org.bson.Document; import org.bson.codecs.DecoderContext; import org.junit.jupiter.api.Test; +import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.expression.EvaluationContext; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -264,10 +265,60 @@ void bindQuotedMulitParameterInArray() { assertThat(target).isEqualTo(Document.parse("{\"$and\": [{\"v1\": {\"$in\": [1]}}]}")); } + @Test // DATAMONGO-2545 + void shouldABindArgumentsViaIndexInSpelExpressions() { + + Object[] args = new Object[] { "yess", "nooo" }; + StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT + .getEvaluationContext(args); + + ParameterBindingJsonReader reader = new ParameterBindingJsonReader( + "{ 'isBatman' : ?#{ T(" + this.getClass().getName() + ").isBatman() ? [0] : [1] }}", + new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext)); + Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build()); + + assertThat(target).isEqualTo(new Document("isBatman", "nooo")); + } + + @Test // DATAMONGO-2545 + void shouldAllowMethodArgumentPlaceholdersInSpelExpressions/*becuase this worked before*/() { + + Object[] args = new Object[] { "yess", "nooo" }; + StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT + .getEvaluationContext(args); + + ParameterBindingJsonReader reader = new ParameterBindingJsonReader( + "{ 'isBatman' : ?#{ T(" + this.getClass().getName() + ").isBatman() ? '?0' : '?1' }}", + new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext)); + Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build()); + + assertThat(target).isEqualTo(new Document("isBatman", "nooo")); + } + + @Test // DATAMONGO-2545 + void shouldAllowMethodArgumentPlaceholdersInQuotedSpelExpressions/*becuase this worked before*/() { + + Object[] args = new Object[] { "yess", "nooo" }; + StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT + .getEvaluationContext(args); + + ParameterBindingJsonReader reader = new ParameterBindingJsonReader( + "{ 'isBatman' : \"?#{ T(" + this.getClass().getName() + ").isBatman() ? '?0' : '?1' }\" }", + new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext)); + Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build()); + + assertThat(target).isEqualTo(new Document("isBatman", "nooo")); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); return new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build()); } + // DATAMONGO-2545 + public static boolean isBatman() { + return false; + } + } From feb3018d197502484ac9ad75b9ae4690b804a475 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 13 May 2020 11:30:16 +0200 Subject: [PATCH 0178/1381] DATAMONGO-2545 - Fix full Query Document binding resulting from SpEL. We reenabled annotated queries using a SpEL expression resulting in the actual query document. Original pull request: #864. --- .../json/ParameterBindingDocumentCodec.java | 24 +++++++++++-- .../util/json/ParameterBindingJsonReader.java | 4 +++ .../ParameterBindingJsonReaderUnitTests.java | 35 +++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index baffcaf8cb..72e6467b91 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -38,6 +38,7 @@ import org.bson.Transformer; import org.bson.codecs.*; import org.bson.codecs.configuration.CodecRegistry; +import org.bson.json.JsonParseException; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; @@ -190,9 +191,26 @@ public Document decode(final BsonReader reader, final DecoderContext decoderCont Document document = new Document(); reader.readStartDocument(); - while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { - String fieldName = reader.readName(); - document.put(fieldName, readValue(reader, decoderContext)); + + try { + + while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { + String fieldName = reader.readName(); + Object value = readValue(reader, decoderContext); + document.put(fieldName, value); + } + } catch (JsonParseException e) { + try { + + Object value = readValue(reader, decoderContext); + if (value instanceof Map) { + if (!((Map) value).isEmpty()) { + return new Document((Map) value); + } + } + } catch (Exception ex) { + throw e; + } } reader.readEndDocument(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index 86e311920a..cb3a08804f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -23,6 +23,7 @@ import java.util.Calendar; import java.util.Date; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; import java.util.function.Supplier; import java.util.regex.Matcher; @@ -493,6 +494,9 @@ private BsonType bsonTypeForValue(Object value) { if (ClassUtils.isAssignable(Iterable.class, type)) { return BsonType.ARRAY; } + if (ClassUtils.isAssignable(Map.class, type)) { + return BsonType.DOCUMENT; + } return BsonType.UNDEFINED; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 6e6e14dbda..93d54f446f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -17,6 +17,9 @@ import static org.assertj.core.api.Assertions.*; +import lombok.AllArgsConstructor; +import lombok.Data; + import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; @@ -310,6 +313,26 @@ void shouldABindArgumentsViaIndexInSpelExpressions() { assertThat(target).isEqualTo(new Document("isBatman", "nooo")); } + @Test // DATAMONGO-2545 + void evaluatesSpelExpressionDefiningEntireQuery() { + + Object[] args = new Object[] {}; + StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT + .getEvaluationContext(args); + evaluationContext.setRootObject(new DummySecurityObject(new DummyWithId("wonderwoman"))); + + String json = "?#{ T(" + this.getClass().getName() + + ").isBatman() ? {'_class': { '$eq' : 'region' }} : { '$and' : { {'_class': { '$eq' : 'region' } }, {'user.superviser': principal.id } } } }"; + + ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, + new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext)); + Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build()); + + assertThat(target) + .isEqualTo(new Document("$and", Arrays.asList(new Document("_class", new Document("$eq", "region")), + new Document("user.superviser", "wonderwoman")))); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); @@ -321,4 +344,16 @@ public static boolean isBatman() { return false; } + @Data + @AllArgsConstructor + public static class DummySecurityObject { + DummyWithId principal; + } + + @Data + @AllArgsConstructor + public static class DummyWithId { + String id; + } + } From 2a150adc4026dab5be397d2d5e84190ecec5b944 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 26 May 2020 09:51:23 +0200 Subject: [PATCH 0179/1381] DATAMONGO-2545 - Polishing. Fix warnings and typos. Original pull request: #864. --- .../mongodb/util/json/ParameterBindingDocumentCodec.java | 6 ++++-- .../util/json/ParameterBindingJsonReaderUnitTests.java | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index 72e6467b91..33eeee9bae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -176,6 +176,7 @@ public Document decode(@Nullable String json, ParameterBindingContext bindingCon return this.decode(reader, DecoderContext.builder().build()); } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Document decode(final BsonReader reader, final DecoderContext decoderContext) { @@ -203,12 +204,13 @@ public Document decode(final BsonReader reader, final DecoderContext decoderCont try { Object value = readValue(reader, decoderContext); - if (value instanceof Map) { + if (value instanceof Map) { if (!((Map) value).isEmpty()) { - return new Document((Map) value); + return new Document((Map) value); } } } catch (Exception ex) { + e.addSuppressed(ex); throw e; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 93d54f446f..6939add042 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -299,7 +299,7 @@ void shouldABindArgumentsViaIndexInSpelExpressions() { } @Test // DATAMONGO-2545 - void shouldAllowMethodArgumentPlaceholdersInQuotedSpelExpressions/*becuase this worked before*/() { + void shouldAllowMethodArgumentPlaceholdersInQuotedSpelExpressions/*because this worked before*/() { Object[] args = new Object[] { "yess", "nooo" }; StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT @@ -322,7 +322,7 @@ void evaluatesSpelExpressionDefiningEntireQuery() { evaluationContext.setRootObject(new DummySecurityObject(new DummyWithId("wonderwoman"))); String json = "?#{ T(" + this.getClass().getName() - + ").isBatman() ? {'_class': { '$eq' : 'region' }} : { '$and' : { {'_class': { '$eq' : 'region' } }, {'user.superviser': principal.id } } } }"; + + ").isBatman() ? {'_class': { '$eq' : 'region' }} : { '$and' : { {'_class': { '$eq' : 'region' } }, {'user.supervisor': principal.id } } } }"; ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext)); @@ -330,7 +330,7 @@ void evaluatesSpelExpressionDefiningEntireQuery() { assertThat(target) .isEqualTo(new Document("$and", Arrays.asList(new Document("_class", new Document("$eq", "region")), - new Document("user.superviser", "wonderwoman")))); + new Document("user.supervisor", "wonderwoman")))); } private static Document parse(String json, Object... args) { From 84ac0e8a85a9fc0b0f47fc45a45a8c90cf4ac6e8 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 12 May 2020 09:39:38 +0200 Subject: [PATCH 0180/1381] DATAMONGO-2542 - Shortcut PersistentPropertyPath resolution during query mapping. By shortcutting the path resolution we avoid checking keywords like $in against a potential path expression. Original pull request: #863. --- .../data/mongodb/core/convert/QueryMapper.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 884446cf81..6434021e59 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -965,7 +965,7 @@ public MetadataBackedField(String name, MongoPersistentEntity entity, this.entity = entity; this.mappingContext = context; - this.path = getPath(removePlaceholders(POSITIONAL_PARAMETER_PATTERN, name)); + this.path = getPath(removePlaceholders(POSITIONAL_PARAMETER_PATTERN, name), property); this.property = path == null ? property : path.getLeafProperty(); this.association = findAssociation(); } @@ -1079,11 +1079,17 @@ protected PersistentPropertyPath getPath() { * @return */ @Nullable - private PersistentPropertyPath getPath(String pathExpression) { + private PersistentPropertyPath getPath(String pathExpression, + MongoPersistentProperty sourceProperty) { String rawPath = removePlaceholders(POSITIONAL_OPERATOR, removePlaceholders(DOT_POSITIONAL_PATTERN, pathExpression)); + if (sourceProperty != null && sourceProperty.getOwner().equals(entity)) { + return mappingContext + .getPersistentPropertyPath(PropertyPath.from(sourceProperty.getName(), entity.getTypeInformation())); + } + PropertyPath path = forName(rawPath); if (path == null || isPathToJavaLangClassProperty(path)) { return null; From af091bf6becb12da0bd25bc4945d2fb82e076166 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 26 May 2020 10:31:42 +0200 Subject: [PATCH 0181/1381] DATAMONGO-2542 - Polishing. Fix nullable annotation. Original pull request: #863. --- .../springframework/data/mongodb/core/convert/QueryMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 6434021e59..14f25c8843 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1080,7 +1080,7 @@ protected PersistentPropertyPath getPath() { */ @Nullable private PersistentPropertyPath getPath(String pathExpression, - MongoPersistentProperty sourceProperty) { + @Nullable MongoPersistentProperty sourceProperty) { String rawPath = removePlaceholders(POSITIONAL_OPERATOR, removePlaceholders(DOT_POSITIONAL_PATTERN, pathExpression)); From e5157f1c17e9a4bb5be5c83d21d229aaae9b6cd0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 8 Jun 2020 15:54:53 +0200 Subject: [PATCH 0182/1381] DATAMONGO-2560 - Upgrade MongoDB drivers to 4.0.4. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f59b2c8bf4..f50a5f840f 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.4.0-SNAPSHOT - 4.0.3 + 4.0.4 ${mongo} 1.19 From 431f7e6b782e04fccb32fd54714d34f3a61f4fee Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 9 Jun 2020 11:13:39 +0200 Subject: [PATCH 0183/1381] DATAMONGO-2562 - Fix return type detection for suspended Kotlin methods. See DATACMNS-1738 for further reference. --- .../query/ReactiveMongoQueryMethod.java | 6 +- ...ctiveMongoQueryMethodCoroutineUnitTests.kt | 61 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java index 391157e355..fdd6773b6f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java @@ -34,6 +34,7 @@ import org.springframework.data.repository.util.ReactiveWrapperConverters; import org.springframework.data.repository.util.ReactiveWrappers; import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.Lazy; import org.springframework.data.util.TypeInformation; import org.springframework.util.ClassUtils; @@ -50,6 +51,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod { private static final ClassTypeInformation SLICE_TYPE = ClassTypeInformation.from(Slice.class); private final Method method; + private final Lazy isCollectionQuery; /** * Creates a new {@link ReactiveMongoQueryMethod} from the given {@link Method}. @@ -92,6 +94,8 @@ public ReactiveMongoQueryMethod(Method method, RepositoryMetadata metadata, Proj } this.method = method; + this.isCollectionQuery = Lazy.of(() -> !(isPageQuery() || isSliceQuery()) + && ReactiveWrappers.isMultiValueType(metadata.getReturnType(method).getType())); } /* @@ -109,7 +113,7 @@ protected MongoParameters createParameters(Method method) { */ @Override public boolean isCollectionQuery() { - return !(isPageQuery() || isSliceQuery()) && ReactiveWrappers.isMultiValueType(method.getReturnType()); + return isCollectionQuery.get(); } /* diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt new file mode 100644 index 0000000000..ea77b86e93 --- /dev/null +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2020 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 + * + * https://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.repository.query + +import kotlinx.coroutines.flow.Flow +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.data.mongodb.core.mapping.MongoMappingContext +import org.springframework.data.mongodb.repository.Person +import org.springframework.data.projection.SpelAwareProxyProjectionFactory +import org.springframework.data.repository.core.support.DefaultRepositoryMetadata +import org.springframework.data.repository.kotlin.CoroutineCrudRepository +import kotlin.coroutines.Continuation + +/** + * Unit tests for [ReactiveMongoQueryMethod] using Coroutine repositories. + * + * @author Mark Paluch + */ +class ReactiveMongoQueryMethodCoroutineUnitTests { + + val projectionFactory = SpelAwareProxyProjectionFactory() + + interface PersonRepository : CoroutineCrudRepository { + + suspend fun findSuspendAllByName(): Flow + + fun findAllByName(): Flow + } + + @Test // DATAMONGO-2562 + internal fun `should consider methods returning Flow as collection queries`() { + + val method = PersonRepository::class.java.getMethod("findAllByName") + val queryMethod = ReactiveMongoQueryMethod(method, DefaultRepositoryMetadata(PersonRepository::class.java), projectionFactory, MongoMappingContext()) + + assertThat(queryMethod.isCollectionQuery).isTrue() + } + + @Test // DATAMONGO-2562 + internal fun `should consider suspended methods returning Flow as collection queries`() { + + val method = PersonRepository::class.java.getMethod("findSuspendAllByName", Continuation::class.java) + val queryMethod = ReactiveMongoQueryMethod(method, DefaultRepositoryMetadata(PersonRepository::class.java), projectionFactory, MongoMappingContext()) + + assertThat(queryMethod.isCollectionQuery).isTrue() + } +} From 4defad57c9c154e70a019b7721e07da0a453a8f8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 9 Jun 2020 11:14:15 +0200 Subject: [PATCH 0184/1381] DATAMONGO-2562 - Polishing. Fix typo in exception message. --- .../data/mongodb/repository/query/ReactiveMongoQueryMethod.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java index fdd6773b6f..97fc3d55d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java @@ -89,7 +89,7 @@ public ReactiveMongoQueryMethod(Method method, RepositoryMetadata metadata, Proj if (hasParameterOfType(method, Sort.class)) { throw new IllegalStateException(String.format("Method must not have Pageable *and* Sort parameter. " - + "Use sorting capabilities on Pageble instead! Offending method: %s", method.toString())); + + "Use sorting capabilities on Pageable instead! Offending method: %s", method.toString())); } } From 76990f491509481febc28ed9c26cf99a22edd98e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 9 Jun 2020 16:10:27 +0200 Subject: [PATCH 0185/1381] DATAMONGO-2564 - Use standard Spring code of conduct. Using https://github.com/spring-projects/.github/blob/master/CODE_OF_CONDUCT.md. --- CODE_OF_CONDUCT.adoc | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 CODE_OF_CONDUCT.adoc diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc deleted file mode 100644 index 33ae7bc9f1..0000000000 --- a/CODE_OF_CONDUCT.adoc +++ /dev/null @@ -1,27 +0,0 @@ -= Contributor Code of Conduct - -As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, such as physical or electronic addresses, - without explicit permission -* Other unethical or unprofessional conduct - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io. -All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. -Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. - -This Code of Conduct is adapted from the https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]. \ No newline at end of file From 4fdf171f7d2ab9974cd2e5cf3420915a4b975bf7 Mon Sep 17 00:00:00 2001 From: BraveLeeLee <705059237@qq.com> Date: Wed, 10 Jun 2020 15:03:21 +0800 Subject: [PATCH 0186/1381] DATAMONGO-2565 - Evaluate correct expression when obtaining collation from MongoPersistentEntity. Original pull request: #869. --- .../data/mongodb/core/mapping/BasicMongoPersistentEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index e0a1c4d399..74a2d08027 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -164,7 +164,7 @@ public boolean hasTextScoreProperty() { @Override public org.springframework.data.mongodb.core.query.Collation getCollation() { - Object collationValue = collationExpression != null ? expression.getValue(getEvaluationContext(null), String.class) + Object collationValue = collationExpression != null ? collationExpression.getValue(getEvaluationContext(null), String.class) : this.collation; if (collationValue == null) { From efbf9c83058c58287736242c0a4022392e5ae556 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Jun 2020 10:14:26 +0200 Subject: [PATCH 0187/1381] DATAMONGO-2565 - Polishing. Add unit test to verify behavior. Cleanup code. Original pull request: #869. --- .../BasicMongoPersistentEntityUnitTests.java | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java index bdc22b3bd8..a8dd52e6e9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -34,6 +34,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AliasFor; import org.springframework.data.mapping.MappingException; +import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.data.spel.spi.EvaluationContextExtension; import org.springframework.data.util.ClassTypeInformation; @@ -43,6 +44,7 @@ * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) public class BasicMongoPersistentEntityUnitTests { @@ -53,7 +55,7 @@ public class BasicMongoPersistentEntityUnitTests { @Test void subclassInheritsAtDocumentAnnotation() { - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(Person.class)); assertThat(entity.getCollection()).isEqualTo("contacts"); } @@ -61,7 +63,7 @@ void subclassInheritsAtDocumentAnnotation() { @Test void evaluatesSpELExpression() { - MongoPersistentEntity entity = new BasicMongoPersistentEntity( + MongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(Company.class)); assertThat(entity.getCollection()).isEqualTo("35"); } @@ -74,7 +76,7 @@ void collectionAllowsReferencingSpringBean() { when(context.getBean("myBean")).thenReturn(provider); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(DynamicallyMapped.class)); entity.setEvaluationContextProvider(new ExtensionAwareEvaluationContextProvider(context)); @@ -87,7 +89,7 @@ void collectionAllowsReferencingSpringBean() { @Test // DATAMONGO-937 void shouldDetectLanguageCorrectly() { - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(DocumentWithLanguage.class)); assertThat(entity.getLanguage()).isEqualTo("spanish"); @@ -99,11 +101,11 @@ void verifyShouldThrowExceptionForInvalidTypeOfExplicitLanguageProperty() { doReturn(true).when(propertyMock).isExplicitLanguageProperty(); doReturn(Number.class).when(propertyMock).getActualType(); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); entity.addPersistentProperty(propertyMock); - assertThatExceptionOfType(MappingException.class).isThrownBy(() -> entity.verify()); + assertThatExceptionOfType(MappingException.class).isThrownBy(entity::verify); } @Test // DATAMONGO-1053 @@ -112,7 +114,7 @@ void verifyShouldPassForStringAsExplicitLanguageProperty() { doReturn(true).when(propertyMock).isExplicitLanguageProperty(); doReturn(String.class).when(propertyMock).getActualType(); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); entity.addPersistentProperty(propertyMock); @@ -125,7 +127,7 @@ void verifyShouldPassForStringAsExplicitLanguageProperty() { @Test // DATAMONGO-1053 void verifyShouldIgnoreNonExplicitLanguageProperty() { - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); when(propertyMock.isExplicitLanguageProperty()).thenReturn(false); entity.addPersistentProperty(propertyMock); @@ -147,11 +149,11 @@ void verifyShouldThrowErrorForLazyDBRefOnFinalClass() { doReturn(dbRefMock).when(propertyMock).getDBRef(); doReturn(true).when(dbRefMock).lazy(); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); entity.addPersistentProperty(propertyMock); - assertThatExceptionOfType(MappingException.class).isThrownBy(() -> entity.verify()); + assertThatExceptionOfType(MappingException.class).isThrownBy(entity::verify); } @Test // DATAMONGO-1157 @@ -165,11 +167,11 @@ void verifyShouldThrowErrorForLazyDBRefArray() { doReturn(dbRefMock).when(propertyMock).getDBRef(); doReturn(true).when(dbRefMock).lazy(); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); entity.addPersistentProperty(propertyMock); - assertThatExceptionOfType(MappingException.class).isThrownBy(() -> entity.verify()); + assertThatExceptionOfType(MappingException.class).isThrownBy(entity::verify); } @Test // DATAMONGO-1157 @@ -183,7 +185,7 @@ void verifyShouldPassForLazyDBRefOnNonArrayNonFinalClass() { doReturn(dbRefMock).when(propertyMock).getDBRef(); doReturn(true).when(dbRefMock).lazy(); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); entity.addPersistentProperty(propertyMock); entity.verify(); @@ -201,7 +203,7 @@ void verifyShouldPassForNonLazyDBRefOnFinalClass() { doReturn(dbRefMock).when(propertyMock).getDBRef(); doReturn(false).when(dbRefMock).lazy(); - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(AnyDocument.class)); entity.addPersistentProperty(propertyMock); entity.verify(); @@ -212,7 +214,7 @@ void verifyShouldPassForNonLazyDBRefOnFinalClass() { @Test // DATAMONGO-1291 void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation() { - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(DocumentWithCustomAnnotation.class)); assertThat(entity.getCollection()).isEqualTo("collection-1"); @@ -221,7 +223,7 @@ void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation() { @Test // DATAMONGO-1373 void metaInformationShouldBeReadCorrectlyFromComposedDocumentAnnotation() { - BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(DocumentWithComposedAnnotation.class)); assertThat(entity.getCollection()).isEqualTo("custom-collection"); @@ -233,7 +235,7 @@ void usesEvaluationContextExtensionInDynamicDocumentName() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(MappedWithExtension.class)); entity.setEvaluationContextProvider( - new ExtensionAwareEvaluationContextProvider(Arrays.asList(new SampleExtension()))); + new ExtensionAwareEvaluationContextProvider(Collections.singletonList(new SampleExtension()))); assertThat(entity.getCollection()).isEqualTo("collectionName"); } @@ -256,6 +258,18 @@ void readsDocumentCollation() { assertThat(entity.getCollation()).isEqualTo(org.springframework.data.mongodb.core.query.Collation.of("en_US")); } + @Test // DATAMONGO-2565 + void usesCorrectExpressionsForCollectionAndCollation() { + + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( + ClassTypeInformation.from(WithCollectionAndCollationFromSpEL.class)); + entity.setEvaluationContextProvider( + new ExtensionAwareEvaluationContextProvider(Collections.singletonList(new SampleExtension()))); + + assertThat(entity.getCollection()).isEqualTo("collectionName"); + assertThat(entity.getCollation()).isEqualTo(Collation.of("en_US")); + } + @Test // DATAMONGO-2341 void detectsShardedEntityCorrectly() { @@ -340,6 +354,9 @@ class MappedWithExtension {} @Document(collation = "#{myCollation}") class WithCollationFromSpEL {} + @Document(collection = "#{myProperty}", collation = "#{myCollation}") + class WithCollectionAndCollationFromSpEL {} + @Document(collation = "en_US") class WithSimpleCollation {} From 083050fc3c26c652c5b217353bcc588b0aad0c82 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Jun 2020 10:53:01 +0200 Subject: [PATCH 0188/1381] DATAMONGO-2532 - Updated changelog. --- src/main/resources/changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 5b7cdacdbe..ee1dea157e 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.18.RELEASE (2020-06-10) +---------------------------------------------- +* DATAMONGO-2547 - java.lang.IllegalArgumentException: com.mongodb.client.MongoDatabase referenced from a method is not visible from class loader. +* DATAMONGO-2535 - Remove Travis CI. +* DATAMONGO-2532 - Release 2.1.18 (Lovelace SR18). + + Changes in version 3.0.0.RELEASE (2020-05-12) --------------------------------------------- * DATAMONGO-2541 - Upgrade to MongoDB 4.0.3 Drivers. From ffd4166b651ed387034cd125ab844dcc89f95a5e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Jun 2020 12:10:46 +0200 Subject: [PATCH 0189/1381] DATAMONGO-2533 - Updated changelog. --- src/main/resources/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index ee1dea157e..2ad705d903 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,17 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.8.RELEASE (2020-06-10) +--------------------------------------------- +* DATAMONGO-2565 - MongoPersistentEntity.getCollation(...) evaluates document expression instead of collation expression. +* DATAMONGO-2547 - java.lang.IllegalArgumentException: com.mongodb.client.MongoDatabase referenced from a method is not visible from class loader. +* DATAMONGO-2545 - Backwards incompatibilities on @Query. +* DATAMONGO-2542 - Don't attempt to map query operator keywords to properties. +* DATAMONGO-2535 - Remove Travis CI. +* DATAMONGO-2533 - Release 2.2.8 (Moore SR8). +* DATAMONGO-2509 - Polish documentation for 3.0 release. + + Changes in version 2.1.18.RELEASE (2020-06-10) ---------------------------------------------- * DATAMONGO-2547 - java.lang.IllegalArgumentException: com.mongodb.client.MongoDatabase referenced from a method is not visible from class loader. @@ -3036,3 +3047,4 @@ Repository + From 837b333d7aaa18532cb54bf1be3dcec4f6a17d05 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Jun 2020 14:01:47 +0200 Subject: [PATCH 0190/1381] DATAMONGO-2543 - Updated changelog. --- src/main/resources/changelog.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 2ad705d903..f70ce8e4bd 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,18 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.1.RELEASE (2020-06-10) +--------------------------------------------- +* DATAMONGO-2565 - MongoPersistentEntity.getCollation(...) evaluates document expression instead of collation expression. +* DATAMONGO-2562 - CoroutineCrudRepository findAllBy throwing IncorrectResultSizeDataAccessException when more than 1 result. +* DATAMONGO-2560 - Upgrade MongoDB drivers to 4.0.4. +* DATAMONGO-2553 - Reference documentation contains links to removed sections. +* DATAMONGO-2547 - java.lang.IllegalArgumentException: com.mongodb.client.MongoDatabase referenced from a method is not visible from class loader. +* DATAMONGO-2545 - Backwards incompatibilities on @Query. +* DATAMONGO-2543 - Release 3.0.1 (Neumann SR1). +* DATAMONGO-2542 - Don't attempt to map query operator keywords to properties. + + Changes in version 2.2.8.RELEASE (2020-06-10) --------------------------------------------- * DATAMONGO-2565 - MongoPersistentEntity.getCollation(...) evaluates document expression instead of collation expression. @@ -3048,3 +3060,4 @@ Repository + From 61a228f8ac6ef5612d0ac1e160b0a2c0405f4fec Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 15 Jun 2020 14:03:01 +0200 Subject: [PATCH 0191/1381] DATAMONGO-2572 - Remove usage of Oppressive Language. Replaced blacklist with denylist and introduce meta keyword SECONDARY_READS as we no longer use MongoDB API with the initial replication concept. Original Pull Request: #870 --- .../data/mongodb/core/MongoTemplate.java | 8 ++++--- .../mongodb/core/ReactiveMongoTemplate.java | 5 ++-- ...DelegatingAggregationOperationContext.java | 18 +++++++------- .../core/messaging/ChangeStreamTask.java | 4 ++-- .../data/mongodb/core/query/Meta.java | 14 ++++++++++- .../data/mongodb/core/query/Query.java | 17 ++++++++++++- .../data/mongodb/config/spring-mongo-1.0.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.1.xsd | 2 +- .../mongodb/config/spring-mongo-1.10.2.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.10.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.2.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.3.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.4.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.5.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.7.xsd | 2 +- .../data/mongodb/config/spring-mongo-1.8.xsd | 2 +- .../data/mongodb/core/MongoTemplateTests.java | 8 +++---- .../mongodb/core/MongoTemplateUnitTests.java | 24 +++++++++---------- .../core/ReactiveMongoTemplateUnitTests.java | 18 +++++++------- .../data/mongodb/core/query/QueryTests.java | 4 ++-- .../query/MongoQueryMethodUnitTests.java | 6 ++--- 21 files changed, 88 insertions(+), 58 deletions(-) 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 3dc23dd945..d1f1790c7d 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 @@ -1172,7 +1172,7 @@ protected void ensureNotIterable(@Nullable Object o) { /** * Prepare the collection before any processing is done using it. This allows a convenient way to apply settings like - * slaveOk() etc. Can be overridden in sub-classes. + * withCodecRegistry() etc. Can be overridden in sub-classes. * * @param collection */ @@ -3274,6 +3274,7 @@ public FindIterable prepare(FindIterable iterable) { case PARTIAL: cursorToUse = cursorToUse.partial(true); break; + case SECONDARY_READS: case SLAVE_OK: break; default: @@ -3291,7 +3292,8 @@ public FindIterable prepare(FindIterable iterable) { @Override public ReadPreference getReadPreference() { - return query.getMeta().getFlags().contains(CursorOption.SLAVE_OK) ? ReadPreference.primaryPreferred() : null; + return (query.getMeta().getFlags().contains(CursorOption.SECONDARY_READS) + || query.getMeta().getFlags().contains(CursorOption.SLAVE_OK)) ? ReadPreference.primaryPreferred() : null; } } @@ -3368,7 +3370,7 @@ static class CloseableIterableCursorAdapter implements CloseableIterator { CloseableIterableCursorAdapter(MongoCursor cursor, PersistenceExceptionTranslator exceptionTranslator, DocumentCallback objectReadCallback) { - + this.cursor = cursor; this.exceptionTranslator = exceptionTranslator; this.objectReadCallback = objectReadCallback; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 5abf54a2e2..532ea54aa1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -2679,7 +2679,7 @@ protected void ensureNotIterable(Object o) { /** * Prepare the collection before any processing is done using it. This allows a convenient way to apply settings like - * slaveOk() etc. Can be overridden in sub-classes. + * withCodecRegistry() etc. Can be overridden in sub-classes. * * @param collection */ @@ -3324,7 +3324,8 @@ public FindPublisher prepare(FindPublisher findPublisher) { @Override public ReadPreference getReadPreference() { - return query.getMeta().getFlags().contains(CursorOption.SLAVE_OK) ? ReadPreference.primaryPreferred() : null; + return (query.getMeta().getFlags().contains(CursorOption.SECONDARY_READS) + || query.getMeta().getFlags().contains(CursorOption.SLAVE_OK)) ? ReadPreference.primaryPreferred() : null; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java index b941b801a4..a9d384e108 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java @@ -31,7 +31,7 @@ * {@link AggregationOperationContext} implementation prefixing non-command keys on root level with the given prefix. * Useful when mapping fields to domain specific types while having to prefix keys for query purpose. *

      - * Fields to be excluded from prefixing my be added to a {@literal blacklist}. + * Fields to be excluded from prefixing my be added to a {@literal denylist}. * * @author Christoph Strobl * @author Mark Paluch @@ -41,18 +41,18 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati private final AggregationOperationContext delegate; private final String prefix; - private final Set blacklist; + private final Set denylist; public PrefixingDelegatingAggregationOperationContext(AggregationOperationContext delegate, String prefix) { this(delegate, prefix, Collections.emptySet()); } public PrefixingDelegatingAggregationOperationContext(AggregationOperationContext delegate, String prefix, - Collection blacklist) { + Collection denylist) { this.delegate = delegate; this.prefix = prefix; - this.blacklist = new HashSet<>(blacklist); + this.denylist = new HashSet<>(denylist); } /* @@ -121,7 +121,7 @@ private Document doPrefix(Document source) { } private String prefixKey(String key) { - return (key.startsWith("$") || isBlacklisted(key)) ? key : (prefix + "." + key); + return (key.startsWith("$") || isDenied(key)) ? key : (prefix + "." + key); } private Object prefixCollection(Collection sourceCollection) { @@ -139,9 +139,9 @@ private Object prefixCollection(Collection sourceCollection) { return prefixed; } - private boolean isBlacklisted(String key) { + private boolean isDenied(String key) { - if (blacklist.contains(key)) { + if (denylist.contains(key)) { return true; } @@ -149,8 +149,8 @@ private boolean isBlacklisted(String key) { return false; } - for (String blacklisted : blacklist) { - if (key.startsWith(blacklisted + ".")) { + for (String denied : denylist) { + if (key.startsWith(denied + ".")) { return true; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java index 668316f2a0..2ae3fd92f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java @@ -62,7 +62,7 @@ */ class ChangeStreamTask extends CursorReadingTask, Object> { - private final Set blacklist = new HashSet<>( + private final Set denylist = new HashSet<>( Arrays.asList("operationType", "fullDocument", "documentKey", "updateDescription", "ns")); private final QueryMapper queryMapper; @@ -176,7 +176,7 @@ List prepareFilter(MongoTemplate template, ChangeStreamOptions options template.getConverter().getMappingContext(), queryMapper) : Aggregation.DEFAULT_CONTEXT; - return agg.toPipeline(new PrefixingDelegatingAggregationOperationContext(context, "fullDocument", blacklist)); + return agg.toPipeline(new PrefixingDelegatingAggregationOperationContext(context, "fullDocument", denylist)); } if (filter instanceof List) { 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 a32435c5d0..c865fef800 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 @@ -284,9 +284,21 @@ public enum CursorOption { */ EXHAUST, - /** Allows querying of a replica slave. */ + /** + * Allows querying of a replica. + * + * @deprecated since 3.0.2, use {@link #SECONDARY_READS} instead. + */ + @Deprecated SLAVE_OK, + /** + * Allows querying of a replica. + * + * @since 3.0.2 + */ + SECONDARY_READS, + /** * 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. 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 291af0c655..ec63ac504d 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 @@ -411,18 +411,33 @@ public Query exhaust() { } /** - * Allows querying of a replica slave. + * Allows querying of a replica. * * @return this. * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#SLAVE_OK * @since 1.10 + * @deprecated since 3.0.2, use {@link #allowSecondaryReads()}. */ + @Deprecated public Query slaveOk() { meta.addFlag(Meta.CursorOption.SLAVE_OK); return this; } + /** + * Allows querying of a replica. + * + * @return this. + * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#SECONDARY_READS + * @since 3.0.2 + */ + public Query allowSecondaryReads() { + + meta.addFlag(Meta.CursorOption.SECONDARY_READS); + return this; + } + /** * @return this. * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#PARTIAL diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd index 2b4fbee2b1..a179fdb9fd 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd @@ -434,7 +434,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd index cd81bf328f..5c959b8126 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd @@ -432,7 +432,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd index 1d4a09be13..6c0fcc67c3 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd @@ -531,7 +531,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.xsd index 5d06b0a499..dde5cd0a91 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.10.xsd @@ -531,7 +531,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd index 71dbf87098..f73f940c7c 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd @@ -447,7 +447,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd index 2aa09c0cdd..c9d1b0a254 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd @@ -462,7 +462,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd index 33874b3f26..541661c8c6 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd @@ -480,7 +480,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd index 43ba06bae6..1363480b56 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd @@ -498,7 +498,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.7.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.7.xsd index ecb082e81b..51ff5b3a10 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.7.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.7.xsd @@ -531,7 +531,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.8.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.8.xsd index cb02bb191c..40d6de36d6 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.8.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.8.xsd @@ -537,7 +537,7 @@ This controls whether or not to fsync. The 'fsync' option to the getlasterror c diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index e7027a05a0..f7c308a2f2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -1162,7 +1162,7 @@ public void testFindOneWithSort() { assertThat(p5.getFirstName()).isEqualTo("Mark"); } - @Test + @Test // DATAMONGO-2572 public void testUsingReadPreference() throws Exception { this.template.execute("readPref", new CollectionCallback() { public Object doInCollection(MongoCollection collection) @@ -1173,9 +1173,9 @@ public Object doInCollection(MongoCollection collection) return null; } }); - MongoTemplate slaveTemplate = new MongoTemplate(factory); - slaveTemplate.setReadPreference(ReadPreference.secondary()); - slaveTemplate.execute("readPref", new CollectionCallback() { + MongoTemplate secondaryTemplate = new MongoTemplate(factory); + secondaryTemplate.setReadPreference(ReadPreference.secondary()); + secondaryTemplate.execute("readPref", new CollectionCallback() { public Object doInCollection(MongoCollection collection) throws MongoException, DataAccessException { assertThat(collection.getReadPreference()).isEqualTo(ReadPreference.secondary()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index da6a16c6a4..28f374d2ba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1714,34 +1714,34 @@ void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { Assertions.assertThat(ReflectionTestUtils.getField(template, "entityCallbacks")).isSameAs(callbacks); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { - template.find(new Query().slaveOk(), AutogenerateableId.class); + template.find(new Query().allowSecondaryReads(), AutogenerateableId.class); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { - template.findOne(new Query().slaveOk(), AutogenerateableId.class); + template.findOne(new Query().allowSecondaryReads(), AutogenerateableId.class); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { - template.findDistinct(new Query().slaveOk(), "name", AutogenerateableId.class, String.class); + template.findDistinct(new Query().allowSecondaryReads(), "name", AutogenerateableId.class, String.class); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForStream() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForStream() { - template.stream(new Query().slaveOk(), AutogenerateableId.class); + template.stream(new Query().allowSecondaryReads(), AutogenerateableId.class); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 1dac146e1d..46073a8952 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -896,26 +896,26 @@ void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { Assertions.assertThat(ReflectionTestUtils.getField(template, "entityCallbacks")).isSameAs(callbacks); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { - template.find(new Query().slaveOk(), AutogenerateableId.class).subscribe(); + template.find(new Query().allowSecondaryReads(), AutogenerateableId.class).subscribe(); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { - template.findOne(new Query().slaveOk(), AutogenerateableId.class).subscribe(); + template.findOne(new Query().allowSecondaryReads(), AutogenerateableId.class).subscribe(); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } - @Test // DATAMONGO-2344 - void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { + @Test // DATAMONGO-2344, DATAMONGO-2572 + void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { - template.findDistinct(new Query().slaveOk(), "name", AutogenerateableId.class, String.class).subscribe(); + template.findDistinct(new Query().allowSecondaryReads(), "name", AutogenerateableId.class, String.class).subscribe(); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java index 6e4b920860..1c1ff8c719 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java @@ -297,14 +297,14 @@ void clonedQueryShouldNotDependOnFieldsFromSource() { .isNotEqualTo(source.getFieldsObject()); } - @Test // DATAMONGO-1783 + @Test // DATAMONGO-1783, DATAMONGO-2572 void clonedQueryShouldNotDependOnMetaFromSource() { Query source = new Query().maxTimeMsec(100); Query target = Query.of(source); compareQueries(target, source); - source.slaveOk(); + source.allowSecondaryReads(); Meta meta = new Meta(); meta.setMaxTimeMsec(100); 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 e4d5c84753..18c701306f 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 @@ -194,7 +194,7 @@ public void createsMongoQueryMethodWithNoCursorTimeoutCorrectly() throws Excepti .contains(org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT); } - @Test // DATAMONGO-1480 + @Test // DATAMONGO-1480, DATAMONGO-2572 public void createsMongoQueryMethodWithMultipleFlagsCorrectly() throws Exception { MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithMultipleFlags"); @@ -202,7 +202,7 @@ public void createsMongoQueryMethodWithMultipleFlagsCorrectly() throws Exception assertThat(method.hasQueryMetaAttributes()).isTrue(); assertThat(method.getQueryMetaAttributes().getFlags()).contains( org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT, - org.springframework.data.mongodb.core.query.Meta.CursorOption.SLAVE_OK); + org.springframework.data.mongodb.core.query.Meta.CursorOption.SECONDARY_READS); } @Test // DATAMONGO-1266 @@ -273,7 +273,7 @@ interface PersonRepository extends Repository { List metaWithNoCursorTimeout(); @Meta(flags = { org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT, - org.springframework.data.mongodb.core.query.Meta.CursorOption.SLAVE_OK }) + org.springframework.data.mongodb.core.query.Meta.CursorOption.SECONDARY_READS }) List metaWithMultipleFlags(); // DATAMONGO-1266 From f7689066842c20b8c9b201c2d3e485fa02f9c2a3 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 17 Jun 2020 10:31:31 +0200 Subject: [PATCH 0192/1381] DATAMONGO-2572 - Remove trailing whitespaces from xsd files. Original Pull Request: #870 --- .../data/mongodb/config/spring-mongo-1.0.xsd | 28 +++---- .../data/mongodb/config/spring-mongo-1.1.xsd | 28 +++---- .../data/mongodb/config/spring-mongo-1.2.xsd | 30 +++---- .../data/mongodb/config/spring-mongo-1.3.xsd | 32 ++++---- .../data/mongodb/config/spring-mongo-1.4.xsd | 34 ++++---- .../data/mongodb/config/spring-mongo-1.5.xsd | 32 ++++---- .../data/mongodb/config/spring-mongo-1.7.xsd | 82 +++++++++---------- .../data/mongodb/config/spring-mongo-1.8.xsd | 68 +++++++-------- .../data/mongodb/config/mongo.properties | 1 - 9 files changed, 167 insertions(+), 168 deletions(-) diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd index a179fdb9fd..a0d95f2425 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd @@ -318,8 +318,8 @@ The Mongo driver options - - @@ -348,14 +348,14 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -363,22 +363,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -395,18 +395,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -430,14 +430,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + @@ -466,4 +466,4 @@ This controls if the driver is allowed to read from secondaries or replicas. De - \ No newline at end of file + diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd index 5c959b8126..dd7287dab3 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.1.xsd @@ -316,8 +316,8 @@ The Mongo driver options - - @@ -346,14 +346,14 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -361,22 +361,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -393,18 +393,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -428,14 +428,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + @@ -464,4 +464,4 @@ This controls if the driver is allowed to read from secondaries or replicas. De - \ No newline at end of file + diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd index f73f940c7c..cf995f23cd 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.2.xsd @@ -230,7 +230,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -331,8 +331,8 @@ The Mongo driver options - - @@ -361,14 +361,14 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -376,22 +376,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -408,18 +408,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -443,14 +443,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + @@ -479,4 +479,4 @@ This controls if the driver is allowed to read from secondaries or replicas. De - \ No newline at end of file + diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd index c9d1b0a254..c1b6b1df34 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd @@ -234,7 +234,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -346,8 +346,8 @@ The Mongo driver options - - @@ -376,14 +376,14 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -391,22 +391,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -423,18 +423,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -458,14 +458,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + @@ -557,7 +557,7 @@ The reference to a Mongoconverter instance. - + - \ No newline at end of file + diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd index 541661c8c6..78f1dabe14 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd @@ -241,7 +241,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -300,7 +300,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -364,8 +364,8 @@ The Mongo driver options - - @@ -394,14 +394,14 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -409,22 +409,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -441,18 +441,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -476,14 +476,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + - + - \ No newline at end of file + diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd index 1363480b56..0b67ea4db8 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.5.xsd @@ -248,7 +248,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -318,7 +318,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -382,8 +382,8 @@ The Mongo driver options - - @@ -412,14 +412,14 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -427,22 +427,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -459,18 +459,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -494,14 +494,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + - + - + - + @@ -261,7 +261,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -331,7 +331,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -354,7 +354,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -384,7 +384,7 @@ The name of the Mongo object that determines what server to monitor. (by default @@ -410,8 +410,8 @@ The Mongo driver options - - @@ -440,19 +440,19 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -460,22 +460,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -492,18 +492,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -527,14 +527,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + - + @@ -606,11 +606,11 @@ The comma delimited list of username:password@database entries to use for authen - + @@ -626,11 +626,11 @@ The MongoClient description. The minimum number of connections per host. ]]> - + @@ -638,36 +638,36 @@ The number of connections allowed per host. Will block if run out. Default is @@ -684,7 +684,7 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + - + - + @@ -732,7 +732,7 @@ The connect timeout for connections used for the cluster heartbeat. The socket timeout for connections used for the cluster heartbeat. ]]> - + - + @@ -838,7 +838,7 @@ The reference to a Mongoconverter instance. - + - + - + @@ -337,7 +337,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -360,7 +360,7 @@ The name of the Mongo object that determines what server to monitor. (by default - + @@ -416,8 +416,8 @@ The Mongo driver options - - @@ -446,7 +446,7 @@ The host to connect to a MongoDB server. Default is localhost The comma delimited list of host:port entries to use for replica set/pairs. ]]> - + @@ -466,22 +466,22 @@ The number of connections allowed per host. Will block if run out. Default is @@ -498,18 +498,18 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + @@ -533,14 +533,14 @@ This controls timeout for write operations in milliseconds. The 'wtimeout' opti This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. ]]> - + - + - + - + - + @@ -644,36 +644,36 @@ The number of connections allowed per host. Will block if run out. Default is @@ -690,7 +690,7 @@ The socket timeout. 0 is default and infinite. The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. ]]> - + - + - + @@ -738,7 +738,7 @@ The connect timeout for connections used for the cluster heartbeat. The socket timeout for connections used for the cluster heartbeat. ]]> - + - + Date: Tue, 26 May 2020 08:39:58 +0200 Subject: [PATCH 0193/1381] DATAMONGO-2558 - Add integration test for RxJava 3 repositories. Update Javadoc and reference documentation. Original pull request: #866. --- spring-data-mongodb/pom.xml | 7 ++ .../ReactiveMongoRepositoryFactoryBean.java | 1 + ...onvertingReactiveMongoRepositoryTests.java | 107 +++++++++++++++++- .../reactive-mongo-repositories.adoc | 2 + 4 files changed, 111 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index c85d971ad8..285161bc0b 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -136,6 +136,13 @@ true + + io.reactivex.rxjava3 + rxjava + ${rxjava3} + true + + diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java index 85ffd3f8e0..cdbe54c6c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java @@ -35,6 +35,7 @@ * @since 2.0 * @see org.springframework.data.repository.reactive.ReactiveSortingRepository * @see org.springframework.data.repository.reactive.RxJava2SortingRepository + * @see org.springframework.data.repository.reactive.RxJava3SortingRepository */ public class ReactiveMongoRepositoryFactoryBean, S, ID extends Serializable> extends RepositoryFactoryBeanSupport { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java index 63d4b88546..cdce6e20e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java @@ -20,6 +20,7 @@ import io.reactivex.Flowable; import io.reactivex.Maybe; import io.reactivex.observers.TestObserver; +import io.reactivex.rxjava3.subscribers.TestSubscriber; import lombok.Data; import lombok.NoArgsConstructor; import reactor.core.publisher.Flux; @@ -38,6 +39,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort; @@ -45,7 +47,6 @@ import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; import org.springframework.data.repository.reactive.ReactiveSortingRepository; import org.springframework.data.repository.reactive.RxJava2SortingRepository; -import org.springframework.stereotype.Repository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -58,7 +59,12 @@ @ContextConfiguration(classes = ConvertingReactiveMongoRepositoryTests.Config.class) public class ConvertingReactiveMongoRepositoryTests { - @EnableReactiveMongoRepositories(includeFilters = @Filter(value = Repository.class), + @EnableReactiveMongoRepositories( + includeFilters = { @Filter(value = ReactivePersonRepostitory.class, type = FilterType.ASSIGNABLE_TYPE), + @Filter(value = RxJava1PersonRepostitory.class, type = FilterType.ASSIGNABLE_TYPE), + @Filter(value = RxJava2PersonRepostitory.class, type = FilterType.ASSIGNABLE_TYPE), + @Filter(value = RxJava3PersonRepostitory.class, type = FilterType.ASSIGNABLE_TYPE), + @Filter(value = MixedReactivePersonRepostitory.class, type = FilterType.ASSIGNABLE_TYPE) }, considerNestedRepositories = true) @ImportResource("classpath:reactive-infrastructure.xml") static class Config {} @@ -67,6 +73,7 @@ static class Config {} @Autowired ReactivePersonRepostitory reactivePersonRepostitory; @Autowired RxJava1PersonRepostitory rxJava1PersonRepostitory; @Autowired RxJava2PersonRepostitory rxJava2PersonRepostitory; + @Autowired RxJava3PersonRepostitory rxJava3PersonRepostitory; ReactivePerson dave, oliver, carter, boyd, stefan, leroi, alicia; @@ -237,6 +244,85 @@ public void maybeRxJava2QueryMethodShouldWork() { testObserver.assertValue(boyd); } + @Test // DATAMONGO-1610 + public void simpleRxJava3MethodsShouldWork() { + + TestObserver testObserver = rxJava3PersonRepostitory.existsById(dave.getId()).test(); + + testObserver.awaitTerminalEvent(); + testObserver.assertComplete(); + testObserver.assertNoErrors(); + testObserver.assertValue(true); + } + + @Test // DATAMONGO-1610 + public void existsWithSingleRxJava3IdMethodsShouldWork() { + + TestObserver testObserver = rxJava3PersonRepostitory.existsById(io.reactivex.Single.just(dave.getId())) + .test(); + + testObserver.awaitTerminalEvent(); + testObserver.assertComplete(); + testObserver.assertNoErrors(); + testObserver.assertValue(true); + } + + @Test // DATAMONGO-1610 + public void flowableRxJava3QueryMethodShouldWork() throws InterruptedException { + + TestSubscriber testSubscriber = rxJava3PersonRepostitory + .findByFirstnameAndLastname(dave.getFirstname(), dave.getLastname()).test(); + + testSubscriber.await(); + testSubscriber.assertComplete(); + testSubscriber.assertNoErrors(); + testSubscriber.assertValue(dave); + } + + @Test // DATAMONGO-1610 + public void singleProjectedRxJava3QueryMethodShouldWork() throws InterruptedException { + + io.reactivex.rxjava3.observers.TestObserver testObserver = rxJava3PersonRepostitory + .findProjectedByLastname(io.reactivex.rxjava3.core.Maybe.just(carter.getLastname())).test(); + + testObserver.await(); + testObserver.assertComplete(); + testObserver.assertNoErrors(); + + testObserver.assertValue(actual -> { + assertThat(actual.getFirstname()).isEqualTo(carter.getFirstname()); + return true; + }); + } + + @Test // DATAMONGO-1610 + public void observableProjectedRxJava3QueryMethodShouldWork() throws InterruptedException { + + io.reactivex.rxjava3.observers.TestObserver testObserver = rxJava3PersonRepostitory + .findProjectedByLastname(io.reactivex.rxjava3.core.Single.just(carter.getLastname())).test(); + + testObserver.await(); + testObserver.assertComplete(); + testObserver.assertNoErrors(); + + testObserver.assertValue(actual -> { + assertThat(actual.getFirstname()).isEqualTo(carter.getFirstname()); + return true; + }); + } + + @Test // DATAMONGO-1610 + public void maybeRxJava3QueryMethodShouldWork() throws InterruptedException { + + io.reactivex.rxjava3.observers.TestObserver testObserver = rxJava3PersonRepostitory + .findByLastname(boyd.getLastname()).test(); + + testObserver.await(); + testObserver.assertComplete(); + testObserver.assertNoErrors(); + testObserver.assertValue(boyd); + } + @Test // DATAMONGO-1444 public void mixedRepositoryShouldWork() { @@ -280,13 +366,11 @@ public void shouldFindByPublisherOfLastNameInAndAgeGreater() { assertThat(people).contains(carter, dave); } - @Repository interface ReactivePersonRepostitory extends ReactiveSortingRepository { Publisher findByLastname(String lastname); } - @Repository interface RxJava1PersonRepostitory extends org.springframework.data.repository.Repository { Observable findByFirstnameAndLastname(String firstname, String lastname); @@ -300,7 +384,6 @@ interface RxJava1PersonRepostitory extends org.springframework.data.repository.R Single existsById(Single id); } - @Repository interface RxJava2PersonRepostitory extends RxJava2SortingRepository { Flowable findByFirstnameAndLastname(String firstname, String lastname); @@ -312,7 +395,19 @@ interface RxJava2PersonRepostitory extends RxJava2SortingRepository findProjectedByLastname(Single lastname); } - @Repository + interface RxJava3PersonRepostitory extends RxJava2SortingRepository { + + io.reactivex.rxjava3.core.Flowable findByFirstnameAndLastname(String firstname, String lastname); + + io.reactivex.rxjava3.core.Maybe findByLastname(String lastname); + + io.reactivex.rxjava3.core.Single findProjectedByLastname( + io.reactivex.rxjava3.core.Maybe lastname); + + io.reactivex.rxjava3.core.Observable findProjectedByLastname( + io.reactivex.rxjava3.core.Single lastname); + } + interface MixedReactivePersonRepostitory extends ReactiveMongoRepository { Single findByLastname(String lastname); diff --git a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc index c9c54cc807..e0aea3b00b 100644 --- a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc +++ b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc @@ -16,6 +16,8 @@ Spring Data's Repository abstraction is a dynamic API, mostly defined by you and * `ReactiveSortingRepository` * `RxJava2CrudRepository` * `RxJava2SortingRepository` +* `RxJava3CrudRepository` +* `RxJava3SortingRepository` Spring Data converts reactive wrapper types behind the scenes so that you can stick to your favorite composition library. From a27939808b4e48234896b2cb1f73e8127be28560 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 26 May 2020 08:39:58 +0200 Subject: [PATCH 0194/1381] DATAMONGO-2558 - Polishing. Fixed issue number in tests. Original pull request: #866. --- .../ConvertingReactiveMongoRepositoryTests.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java index cdce6e20e2..98fcbca802 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ConvertingReactiveMongoRepositoryTests.java @@ -244,7 +244,7 @@ public void maybeRxJava2QueryMethodShouldWork() { testObserver.assertValue(boyd); } - @Test // DATAMONGO-1610 + @Test // DATAMONGO-2558 public void simpleRxJava3MethodsShouldWork() { TestObserver testObserver = rxJava3PersonRepostitory.existsById(dave.getId()).test(); @@ -255,7 +255,7 @@ public void simpleRxJava3MethodsShouldWork() { testObserver.assertValue(true); } - @Test // DATAMONGO-1610 + @Test // DATAMONGO-2558 public void existsWithSingleRxJava3IdMethodsShouldWork() { TestObserver testObserver = rxJava3PersonRepostitory.existsById(io.reactivex.Single.just(dave.getId())) @@ -267,7 +267,7 @@ public void existsWithSingleRxJava3IdMethodsShouldWork() { testObserver.assertValue(true); } - @Test // DATAMONGO-1610 + @Test // DATAMONGO-2558 public void flowableRxJava3QueryMethodShouldWork() throws InterruptedException { TestSubscriber testSubscriber = rxJava3PersonRepostitory @@ -279,7 +279,7 @@ public void flowableRxJava3QueryMethodShouldWork() throws InterruptedException { testSubscriber.assertValue(dave); } - @Test // DATAMONGO-1610 + @Test // DATAMONGO-2558 public void singleProjectedRxJava3QueryMethodShouldWork() throws InterruptedException { io.reactivex.rxjava3.observers.TestObserver testObserver = rxJava3PersonRepostitory @@ -295,7 +295,7 @@ public void singleProjectedRxJava3QueryMethodShouldWork() throws InterruptedExce }); } - @Test // DATAMONGO-1610 + @Test // DATAMONGO-2558 public void observableProjectedRxJava3QueryMethodShouldWork() throws InterruptedException { io.reactivex.rxjava3.observers.TestObserver testObserver = rxJava3PersonRepostitory @@ -311,7 +311,7 @@ public void observableProjectedRxJava3QueryMethodShouldWork() throws Interrupted }); } - @Test // DATAMONGO-1610 + @Test // DATAMONGO-2558 public void maybeRxJava3QueryMethodShouldWork() throws InterruptedException { io.reactivex.rxjava3.observers.TestObserver testObserver = rxJava3PersonRepostitory From a4ef46d641d825768efcd0fb7a68ebabaacc24ea Mon Sep 17 00:00:00 2001 From: Mehran Behnam Date: Thu, 18 Jun 2020 13:00:06 +0430 Subject: [PATCH 0195/1381] DATAMONGO-2570 - Change type of count variable to primitive. Avoiding unintentional unboxing. Original pull request: #871. --- .../data/mongodb/repository/support/SimpleMongoRepository.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index 8244e5b3c9..cf0d696efa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -50,6 +50,7 @@ * @author Christoph Strobl * @author Thomas Darimont * @author Mark Paluch + * @author Mehran Behnam */ public class SimpleMongoRepository implements MongoRepository { @@ -224,7 +225,7 @@ public Page findAll(Pageable pageable) { Assert.notNull(pageable, "Pageable must not be null!"); - Long count = count(); + long count = count(); List list = findAll(new Query().with(pageable)); return new PageImpl<>(list, pageable, count); From c4ae269b143ea52be4f217c70616da63b4beb274 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 22 Jun 2020 10:38:54 +0200 Subject: [PATCH 0196/1381] DATAMONGO-2570 - Polishing. Add assertions. Use method references where possible. Original pull request: #871. --- .../mongodb/repository/support/SimpleMongoRepository.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index cf0d696efa..b00ca61a34 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -98,7 +98,7 @@ public List saveAll(Iterable entities) { Assert.notNull(entities, "The given Iterable of entities not be null!"); Streamable source = Streamable.of(entities); - boolean allNew = source.stream().allMatch(it -> entityInformation.isNew(it)); + boolean allNew = source.stream().allMatch(entityInformation::isNew); if (allNew) { @@ -212,6 +212,8 @@ public List findAll() { @Override public Iterable findAllById(Iterable ids) { + Assert.notNull(ids, "The given Ids of entities not be null!"); + return findAll(new Query(new Criteria(entityInformation.getIdAttribute()) .in(Streamable.of(ids).stream().collect(StreamUtils.toUnmodifiableList())))); } From 1290898c2b82ea53bc2ee68c36bec8ed6d229e6f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 26 May 2020 14:07:58 +0200 Subject: [PATCH 0197/1381] DATAMONGO-2556 - Add estimatedCount for collections. The newly introduced methods delegate to the drivers MongoCollection.estimatedDocumentCount. Original pull request: #867. --- .../data/mongodb/core/MongoOperations.java | 23 ++++++++++++++++ .../data/mongodb/core/MongoTemplate.java | 13 ++++++++++ .../mongodb/core/ReactiveMongoOperations.java | 23 ++++++++++++++++ .../mongodb/core/ReactiveMongoTemplate.java | 26 ++++++++++++------- .../mongodb/core/MongoTemplateUnitTests.java | 10 +++++++ .../core/ReactiveMongoTemplateUnitTests.java | 10 +++++++ 6 files changed, 95 insertions(+), 10 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index bb6c402fb7..b1c5d3ee48 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -1184,6 +1184,29 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option */ long count(Query query, String collectionName); + /** + * Estimate the number of documents, in the collection {@link #getCollectionName(Class) identified by the given type}, + * based on collection statistics. + * + * @param entityClass must not be {@literal null}. + * @return the estimated number of documents. + * @since 3.1 + */ + default long estimatedCount(Class entityClass) { + + Assert.notNull(entityClass, "Entity class must not be null!"); + return estimatedCount(getCollectionName(entityClass)); + } + + /** + * Estimate the number of documents in the given collection based on collection statistics. + * + * @param collectionName must not be {@literal null}. + * @return the estimated number of documents. + * @since 3.1 + */ + long estimatedCount(String collectionName); + /** * Returns the number of documents for the given {@link Query} by querying the given collection using the given entity * class to map the given {@link Query}.
      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 d1f1790c7d..91242611bf 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 @@ -1134,6 +1134,19 @@ protected long doCount(String collectionName, Document filter, CountOptions opti collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options)); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.MongoOperations#estimatedCount(java.lang.String) + */ + @Override + public long estimatedCount(String collectionName) { + return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions()); + } + + protected long doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) { + return execute(collectionName, collection -> collection.estimatedDocumentCount(options)); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.MongoOperations#insert(java.lang.Object) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 9bf4514b33..94fc8843f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -980,6 +980,29 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions */ Mono count(Query query, @Nullable Class entityClass, String collectionName); + /** + * Estimate the number of documents, in the collection {@link #getCollectionName(Class) identified by the given type}, + * based on collection statistics. + * + * @param entityClass must not be {@literal null}. + * @return a {@link Mono} emitting the estimated number of documents. + * @since 3.1 + */ + default Mono estimatedCount(Class entityClass) { + + Assert.notNull(entityClass, "Entity class must not be null!"); + return estimatedCount(getCollectionName(entityClass)); + } + + /** + * Estimate the number of documents in the given collection based on collection statistics. + * + * @param collectionName must not be {@literal null}. + * @return a {@link Mono} emitting the estimated number of documents. + * @since 3.1 + */ + Mono estimatedCount(String collectionName); + /** * Insert the object into the collection for the entity type of the object to save. *

      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 532ea54aa1..336010434d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,6 +17,7 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import com.mongodb.client.model.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -116,16 +117,6 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; -import com.mongodb.client.model.CountOptions; -import com.mongodb.client.model.CreateCollectionOptions; -import com.mongodb.client.model.DeleteOptions; -import com.mongodb.client.model.FindOneAndDeleteOptions; -import com.mongodb.client.model.FindOneAndReplaceOptions; -import com.mongodb.client.model.FindOneAndUpdateOptions; -import com.mongodb.client.model.ReplaceOptions; -import com.mongodb.client.model.ReturnDocument; -import com.mongodb.client.model.UpdateOptions; -import com.mongodb.client.model.ValidationOptions; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertOneResult; @@ -1247,6 +1238,15 @@ public Mono count(Query query, @Nullable Class entityClass, String coll }); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#estimatedCount(java.lang.String) + */ + @Override + public Mono estimatedCount(String collectionName) { + return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions()); + } + /** * Run the actual count operation against the collection with given name. * @@ -1261,6 +1261,12 @@ protected Mono doCount(String collectionName, Document filter, CountOption collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options)); } + protected Mono doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) { + + return createMono(collectionName, + collection -> collection.estimatedDocumentCount(options)); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#insert(reactor.core.publisher.Mono) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 28f374d2ba..f5cddf9d85 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -177,6 +177,7 @@ void beforeEach() { when(collection.mapReduce(any(), any(), eq(Document.class))).thenReturn(mapReduceIterable); when(collection.countDocuments(any(Bson.class), any(CountOptions.class))).thenReturn(1L); // TODO: MongoDB 4 - fix // me + when(collection.estimatedDocumentCount(any())).thenReturn(1L); when(collection.getNamespace()).thenReturn(new MongoNamespace("db.mock-collection")); when(collection.aggregate(any(List.class), any())).thenReturn(aggregateIterable); when(collection.withReadPreference(any())).thenReturn(collection); @@ -2153,6 +2154,15 @@ public void onAfterSave(AfterSaveEvent event) { assertThat(saved.id).isEqualTo("after-save-event"); } + @Test // DATAMONGO-2556 + void esitmatedCountShouldBeDelegatedCorrectly() { + + template.estimatedCount(Person.class); + + verify(db).getCollection("star-wars", Document.class); + verify(collection).estimatedDocumentCount(any()); + } + class AutogenerateableId { @Id BigInteger id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 46073a8952..bd310e872d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -158,6 +158,7 @@ void beforeEach() { when(collection.aggregate(anyList())).thenReturn(aggregatePublisher); when(collection.aggregate(anyList(), any(Class.class))).thenReturn(aggregatePublisher); when(collection.countDocuments(any(), any(CountOptions.class))).thenReturn(Mono.just(0L)); + when(collection.estimatedDocumentCount(any())).thenReturn(Mono.just(0L)); when(collection.updateOne(any(), any(Bson.class), any(UpdateOptions.class))).thenReturn(updateResultPublisher); when(collection.updateMany(any(Bson.class), any(Bson.class), any())).thenReturn(updateResultPublisher); when(collection.updateOne(any(), anyList(), any())).thenReturn(updateResultPublisher); @@ -1365,6 +1366,15 @@ public void onAfterSave(AfterSaveEvent event) { assertThat(saved.id).isEqualTo("after-save-event"); } + @Test // DATAMONGO-2556 + void esitmatedCountShouldBeDelegatedCorrectly() { + + template.estimatedCount(Person.class).subscribe(); + + verify(db).getCollection("star-wars", Document.class); + verify(collection).estimatedDocumentCount(any()); + } + private void stubFindSubscribe(Document document) { Publisher realPublisher = Flux.just(document); From 2eaa2d38af3113a81120c7714007d224dac7ec23 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 26 May 2020 14:09:04 +0200 Subject: [PATCH 0198/1381] DATAMONGO-2556 - Polishing. Original pull request: #867. --- .../springframework/data/mongodb/core/MongoTemplate.java | 8 ++++---- .../data/mongodb/core/ReactiveMongoTemplate.java | 7 +++---- .../data/mongodb/core/MongoTemplateUnitTests.java | 3 +-- 3 files changed, 8 insertions(+), 10 deletions(-) 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 91242611bf..d37c9888af 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 @@ -3015,8 +3015,8 @@ private static class FindAndModifyCallback implements CollectionCallback arrayFilters; private final FindAndModifyOptions options; - FindAndModifyCallback(Document query, Document fields, Document sort, Object update, - List arrayFilters, FindAndModifyOptions options) { + FindAndModifyCallback(Document query, Document fields, Document sort, Object update, List arrayFilters, + FindAndModifyOptions options) { this.query = query; this.fields = fields; @@ -3373,8 +3373,8 @@ static class CloseableIterableCursorAdapter implements CloseableIterator { * @param exceptionTranslator * @param objectReadCallback */ - CloseableIterableCursorAdapter(MongoIterable cursor, - PersistenceExceptionTranslator exceptionTranslator, DocumentCallback objectReadCallback) { + CloseableIterableCursorAdapter(MongoIterable cursor, PersistenceExceptionTranslator exceptionTranslator, + DocumentCallback objectReadCallback) { this.cursor = cursor.iterator(); this.exceptionTranslator = exceptionTranslator; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 336010434d..03daa82cb4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,7 +17,6 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; -import com.mongodb.client.model.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -117,6 +116,7 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; +import com.mongodb.client.model.*; import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertOneResult; @@ -1244,7 +1244,7 @@ public Mono count(Query query, @Nullable Class entityClass, String coll */ @Override public Mono estimatedCount(String collectionName) { - return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions()); + return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions()); } /** @@ -1263,8 +1263,7 @@ protected Mono doCount(String collectionName, Document filter, CountOption protected Mono doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) { - return createMono(collectionName, - collection -> collection.estimatedDocumentCount(options)); + return createMono(collectionName, collection -> collection.estimatedDocumentCount(options)); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index f5cddf9d85..e0484e225b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -175,8 +175,7 @@ void beforeEach() { when(db.runCommand(any(), any(Class.class))).thenReturn(commandResultDocument); when(collection.find(any(org.bson.Document.class), any(Class.class))).thenReturn(findIterable); when(collection.mapReduce(any(), any(), eq(Document.class))).thenReturn(mapReduceIterable); - when(collection.countDocuments(any(Bson.class), any(CountOptions.class))).thenReturn(1L); // TODO: MongoDB 4 - fix - // me + when(collection.countDocuments(any(Bson.class), any(CountOptions.class))).thenReturn(1L); when(collection.estimatedDocumentCount(any())).thenReturn(1L); when(collection.getNamespace()).thenReturn(new MongoNamespace("db.mock-collection")); when(collection.aggregate(any(List.class), any())).thenReturn(aggregateIterable); From 66dcb8f662a6c9761220275ec1926c4592307b97 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 22 Jun 2020 13:21:32 +0200 Subject: [PATCH 0199/1381] DATAMONGO-2576 - Upgrade to Hibernate Validator 5.4.3. Add also javax.el to avoid failures in early expression language initialization. --- spring-data-mongodb/pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 285161bc0b..ea401d5618 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -199,7 +199,14 @@ org.hibernate hibernate-validator - 5.2.4.Final + 5.4.3.Final + test + + + + org.glassfish + javax.el + 3.0.1-b11 test From 390b5e7b7ebb3649b7d2250f31223b8137273e68 Mon Sep 17 00:00:00 2001 From: konradend Date: Thu, 28 May 2020 10:17:17 +0400 Subject: [PATCH 0200/1381] DATAMONGO-2574 - Do not overwrite contentType for GridFsFile. Original Pull Request: #868 --- .../data/mongodb/gridfs/GridFsOperations.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index 502d210986..8337cc6718 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -140,12 +140,12 @@ default ObjectId store(InputStream content, @Nullable String filename, @Nullable if (StringUtils.hasText(filename)) { uploadBuilder.filename(filename); } - if (StringUtils.hasText(contentType)) { - uploadBuilder.contentType(contentType); - } if (!ObjectUtils.isEmpty(metadata)) { uploadBuilder.metadata(metadata); } + if (StringUtils.hasText(contentType)) { + uploadBuilder.contentType(contentType); + } return store(uploadBuilder.build()); } From a254576a6ea6c71b48d55011cdb81ced953cf23b Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 18 Jun 2020 17:31:24 +0200 Subject: [PATCH 0201/1381] DATAMONGO-2574 - Polishing. Fix issue in reactive API and add unit tests. Original Pull Request: #868 --- .../data/mongodb/gridfs/GridFsOperations.java | 2 +- .../gridfs/ReactiveGridFsOperations.java | 8 +- .../gridfs/GridFsTemplateUnitTests.java | 79 ++++++++++++++++++ .../ReactiveGridFsTemplateUnitTests.java | 83 +++++++++++++++++++ 4 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateUnitTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index 8337cc6718..bd5709ef5a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -129,7 +129,7 @@ default ObjectId store(InputStream content, @Nullable String filename, @Nullable * * @param content must not be {@literal null}. * @param filename must not be {@literal null} or empty. - * @param contentType can be {@literal null}. + * @param contentType can be {@literal null}. If not empty, may override content type within {@literal metadata}. * @param metadata can be {@literal null}. * @return the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just created. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java index fe7f5bd145..ae2f2e1078 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java @@ -135,7 +135,7 @@ default Mono store(Publisher content, @Nullable String fil * * @param content must not be {@literal null}. * @param filename must not be {@literal null} or empty. - * @param contentType can be {@literal null}. + * @param contentType can be {@literal null}. If not empty, may override content type within {@literal metadata}. * @param metadata can be {@literal null}. * @return a {@link Mono} emitting the {@link ObjectId} of the {@link com.mongodb.client.gridfs.model.GridFSFile} just * created. @@ -148,12 +148,12 @@ default Mono store(Publisher content, @Nullable String fil if (StringUtils.hasText(filename)) { uploadBuilder.filename(filename); } - if (StringUtils.hasText(contentType)) { - uploadBuilder.contentType(contentType); - } if (!ObjectUtils.isEmpty(metadata)) { uploadBuilder.metadata(metadata); } + if (StringUtils.hasText(contentType)) { + uploadBuilder.contentType(contentType); + } return store(uploadBuilder.build()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateUnitTests.java new file mode 100644 index 0000000000..d870940753 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateUnitTests.java @@ -0,0 +1,79 @@ +/* + * Copyright 2020 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 + * + * https://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.gridfs; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.bson.Document; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.convert.MongoConverter; + +/** + * @author Christoph Strobl + */ +class GridFsTemplateUnitTests { + + private GridFsTemplateStub template; + + @BeforeEach + void beforeEach() { + template = new GridFsTemplateStub(); + } + + @Test // DATAMONGO-2574 + void contentMetadataDoesNotOverrideContentTypeIfSet() { + + template.onStoreReturn(new ObjectId()); + template.store(new ByteArrayInputStream(new byte[] {}), "filename", "json", new Document("meta", "data")); + + assertThat(template.capturedUpload().getOptions().getContentType()).isEqualTo("json"); + assertThat(template.capturedUpload().getOptions().getMetadata()).containsEntry("meta", "data"); + } + + private static class GridFsTemplateStub extends GridFsTemplate { + + private Object onStoreResult; + private GridFsObject capturedUpload; + + GridFsTemplateStub() { + super(mock(MongoDatabaseFactory.class), mock(MongoConverter.class)); + } + + @Override + public T store(GridFsObject upload) { + + this.capturedUpload = upload; + return (T) onStoreResult; + } + + GridFsTemplateStub onStoreReturn(Object result) { + + this.onStoreResult = result; + return this; + } + + GridFsObject capturedUpload() { + return capturedUpload; + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateUnitTests.java new file mode 100644 index 0000000000..d55cdd5e34 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateUnitTests.java @@ -0,0 +1,83 @@ +/* + * Copyright 2020 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 + * + * https://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.gridfs; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.InputStream; + +import org.bson.Document; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.convert.MongoConverter; + +/** + * @author Christoph Strobl + */ +class ReactiveGridFsTemplateUnitTests { + + private ReactiveGridFsTemplateStub template; + + @BeforeEach + void beforeEach() { + template = new ReactiveGridFsTemplateStub(); + } + + @Test // DATAMONGO-2574 + void contentMetadataDoesNotOverrideContentTypeIfSet() { + + template.onStoreReturn(new ObjectId()); + template.store(Flux.empty(), "filename", "json", new Document("meta", "data")); + + assertThat(template.capturedUpload().getOptions().getContentType()).isEqualTo("json"); + assertThat(template.capturedUpload().getOptions().getMetadata()).containsEntry("meta", "data"); + } + + private static class ReactiveGridFsTemplateStub extends ReactiveGridFsTemplate { + + private Object onStoreResult; + private GridFsObject> capturedUpload; + + ReactiveGridFsTemplateStub() { + super(mock(ReactiveMongoDatabaseFactory.class), mock(MongoConverter.class)); + } + + @Override + public Mono store(GridFsObject> upload) { + + capturedUpload = upload; + return Mono.just((T) onStoreResult); + } + + ReactiveGridFsTemplateStub onStoreReturn(Object result) { + + this.onStoreResult = result; + return this; + } + + GridFsObject> capturedUpload() { + return capturedUpload; + } + } +} From 41e60e5c25f3d9b67c08baef9b18676cdbafc660 Mon Sep 17 00:00:00 2001 From: Dave Perryman Date: Tue, 9 Apr 2019 15:20:55 +0100 Subject: [PATCH 0202/1381] DATAMONGO-1569 - Add support for partial filter expressions in compound index annotations Original Pull Request: #738 --- .../mongodb/core/index/CompoundIndex.java | 10 ++++++++ .../MongoPersistentEntityIndexResolver.java | 5 ++++ ...ersistentEntityIndexResolverUnitTests.java | 23 ++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java index 3141ba3493..b6808dd8f0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java @@ -46,6 +46,7 @@ * @author Philipp Schneider * @author Johno Crawford * @author Christoph Strobl + * @author Dave Perryman */ @Target({ ElementType.TYPE }) @Documented @@ -170,4 +171,13 @@ */ boolean background() default false; + + /** + * Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}. + * + * @return + * @see https://docs.mongodb.com/manual/core/index-partial/ + */ + String partial() default ""; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index ac5d22413f..0c63d65511 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -69,6 +69,7 @@ * @author Thomas Darimont * @author Martin Macko * @author Mark Paluch + * @author Dave Perryman * @since 1.5 */ public class MongoPersistentEntityIndexResolver implements IndexResolver { @@ -380,6 +381,10 @@ protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, St indexDefinition.background(); } + if (StringUtils.hasText(index.partial())) { + indexDefinition.partial(PartialIndexFilter.of(org.bson.Document.parse(index.partial()))); + } + return new IndexDefinitionHolder(dotPath, indexDefinition, collection); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index cd6de29f3e..7630cb70da 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -25,7 +25,7 @@ import java.util.Collections; import java.util.List; -import org.junit.jupiter.api.Test; +import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -54,6 +54,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Dave Perryman */ @RunWith(Suite.class) @SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class, @@ -663,6 +664,21 @@ public void shouldIdentifyRepeatedAnnotationCorrectly() { indexDefinitions.get(1)); } + @Test // DATAMONGO-1569 + public void singleIndexWithPartialFilter() { + + List indexDefinitions = prepareMappingContextAndResolveIndexForType( + SingleCompoundIndexWithPartialFilter.class); + + assertThat(indexDefinitions).hasSize(1); + assertThat(indexDefinitions.get(0).getIndexKeys()).containsEntry("foo", 1).containsEntry("bar", -1); + assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "compound_index_with_partial") + .containsEntry("unique", true).containsEntry("background", true); + assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("partialFilterExpression", + new org.bson.Document().append("bar", new org.bson.Document().append("$exists", true))); + } + + @Document("CompoundIndexOnLevelOne") static class CompoundIndexOnLevelOne { @@ -733,6 +749,11 @@ static class CompoundIndexWithDefExpression {} @CompoundIndex(name = "cmp-idx-one", def = "{'firstname': 1, 'lastname': -1}") @CompoundIndex(name = "cmp-idx-two", def = "{'address.city': -1, 'address.street': 1}") static class RepeatedCompoundIndex {} + + @Document("SingleCompoundIndexWithPartialFilter") + @CompoundIndex(name = "compound_index_with_partial", def = "{'foo': 1, 'bar': -1}", background = true, + unique = true, partial = "{'bar': {$exists: true}}") + static class SingleCompoundIndexWithPartialFilter {} } public static class TextIndexedResolutionTests { From 94a64a156f66e3777039d0d61a17674a94cec2f1 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 18 Jun 2020 15:02:58 +0200 Subject: [PATCH 0203/1381] DATAMONGO-1569 - Add partialFilter to Indexed annotation. Original Pull Request: #738 --- .../data/mongodb/core/index/Indexed.java | 14 +++++++++++++- .../MongoPersistentEntityIndexResolver.java | 17 +++++++++++++++++ ...oPersistentEntityIndexResolverUnitTests.java | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java index ebaa3a96e3..8f2199c93d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java @@ -53,7 +53,8 @@ IndexDirection direction() default IndexDirection.ASCENDING; /** - * If set to true index will skip over any document that is missing the indexed field. + * If set to true index will skip over any document that is missing the indexed field.
      + * Must not be used with {@link #partialFilter()}. * * @return {@literal false} by default. * @see + * Must not be used with {@link #sparse() sparse = true}. + * + * @return empty by default. + * @see https://docs.mongodb.com/manual/core/index-partial/ + * @since 3.1 + */ + String partialFilter() default ""; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index 0c63d65511..aa3578badf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -46,6 +46,7 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.util.TypeInformation; import org.springframework.expression.EvaluationContext; @@ -474,9 +475,25 @@ protected IndexDefinitionHolder createIndexDefinition(String dotPath, String col } } + if (StringUtils.hasText(index.partialFilter())) { + indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), persistentProperty.getOwner())); + } + return new IndexDefinitionHolder(dotPath, indexDefinition, collection); } + private PartialIndexFilter evaluatePartialFilter(String filterExpression, PersistentEntity entity) { + + Object result = evaluate(filterExpression, getEvaluationContextForProperty(entity)); + + if (result instanceof org.bson.Document) { + return PartialIndexFilter.of((org.bson.Document) result); + } + + return PartialIndexFilter.of(BsonUtils.parse(filterExpression, null)); + } + + /** * Creates {@link HashedIndex} wrapped in {@link IndexDefinitionHolder} out of {@link HashIndexed} for a given * {@link MongoPersistentProperty}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 7630cb70da..fbddbdbb3c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -271,6 +271,16 @@ public void resolveExpressionIndexName() { assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my1st"); } + @Test // DATAMONGO-1569 + public void resolvesPartialFilter() { + + List indexDefinitions = prepareMappingContextAndResolveIndexForType( + WithPartialFilter.class); + + assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("partialFilterExpression", + org.bson.Document.parse("{'value': {'$exists': true}}")); + } + @Document("Zero") static class IndexOnLevelZero { @Indexed String indexedProperty; @@ -395,6 +405,11 @@ class WithDuplicateExpiry { static class WithIndexNameAsExpression { @Indexed(name = "#{'my' + 1 + 'st'}") String spelIndexName; } + + @Document + class WithPartialFilter { + @Indexed(partialFilter = "{'value': {'$exists': true}}") String withPartialFilter; + } } @Target({ ElementType.FIELD }) From 613d085bb71ac3e43130cc1d511f6f2ab8922796 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 18 Jun 2020 15:06:04 +0200 Subject: [PATCH 0204/1381] DATAMONGO-1569 - Polishing. Update Javadoc and avoid unrelated index creation during tests due to class path scanning. Original Pull Request: #738 --- .../mongodb/core/index/CompoundIndex.java | 12 +- .../MongoPersistentEntityIndexResolver.java | 4 +- ...ersistentEntityIndexResolverUnitTests.java | 179 +++++++++--------- 3 files changed, 98 insertions(+), 97 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java index b6808dd8f0..373992c99a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java @@ -96,7 +96,8 @@ boolean unique() default false; /** - * If set to true index will skip over any document that is missing the indexed field. + * If set to true index will skip over any document that is missing the indexed field.
      + * Must not be used with {@link #partialFilter()}. * * @return {@literal false} by default. * @see + * Must not be used with {@link #sparse() sparse = true}. * - * @return + * @return empty by default. * @see https://docs.mongodb.com/manual/core/index-partial/ + * @since 3.1 */ - String partial() default ""; + String partialFilter() default ""; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index aa3578badf..6d3b2b612a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -382,8 +382,8 @@ protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, St indexDefinition.background(); } - if (StringUtils.hasText(index.partial())) { - indexDefinition.partial(PartialIndexFilter.of(org.bson.Document.parse(index.partial()))); + if (StringUtils.hasText(index.partialFilter())) { + indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), entity)); } return new IndexDefinitionHolder(dotPath, indexDefinition, collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index fbddbdbb3c..996e380f80 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -282,22 +282,22 @@ public void resolvesPartialFilter() { } @Document("Zero") - static class IndexOnLevelZero { + class IndexOnLevelZero { @Indexed String indexedProperty; } @Document("One") - static class IndexOnLevelOne { + class IndexOnLevelOne { IndexOnLevelZero zero; } @Document("Two") - static class IndexOnLevelTwo { + class IndexOnLevelTwo { IndexOnLevelOne one; } @Document("WithOptionsOnIndexedProperty") - static class WithOptionsOnIndexedProperty { + class WithOptionsOnIndexedProperty { @Indexed(background = true, direction = IndexDirection.DESCENDING, dropDups = true, expireAfterSeconds = 10, sparse = true, unique = true) // @@ -305,23 +305,23 @@ static class WithOptionsOnIndexedProperty { } @Document - static class IndexOnLevelOneWithExplicitlyNamedField { + class IndexOnLevelOneWithExplicitlyNamedField { @Field("customZero") IndexOnLevelZeroWithExplicityNamedField zero; } - static class IndexOnLevelZeroWithExplicityNamedField { + class IndexOnLevelZeroWithExplicityNamedField { @Indexed @Field("customFieldName") String namedProperty; } @Document - static class WrapperOfWithDbRef { + class WrapperOfWithDbRef { WithDbRef nested; } @Document - static class WithDbRef { + class WithDbRef { @Indexed // @DBRef // @@ -329,12 +329,12 @@ static class WithDbRef { } @Document("no-index") - static class NoIndex { + class NoIndex { @Id String id; } @Document - static class IndexedDocumentWithComposedAnnotations { + class IndexedDocumentWithComposedAnnotations { @Id String id; @CustomIndexedAnnotation String fieldWithDifferentIndexName; @@ -372,7 +372,7 @@ static class IndexedDocumentWithComposedAnnotations { } @Document - static class WithExpireAfterAsPlainString { + class WithExpireAfterAsPlainString { @Indexed(expireAfter = "10m") String withTimeout; } @@ -382,12 +382,12 @@ class WithIso8601Style { } @Document - static class WithExpireAfterAsExpression { + class WithExpireAfterAsExpression { @Indexed(expireAfter = "#{10 + 1 + 's'}") String withTimeout; } @Document - static class WithExpireAfterAsExpressionResultingInDuration { + class WithExpireAfterAsExpressionResultingInDuration { @Indexed(expireAfter = "#{T(java.time.Duration).ofSeconds(100)}") String withTimeout; } @@ -402,7 +402,7 @@ class WithDuplicateExpiry { } @Document - static class WithIndexNameAsExpression { + class WithIndexNameAsExpression { @Indexed(name = "#{'my' + 1 + 'st'}") String spelIndexName; } @@ -419,7 +419,7 @@ class WithPartialFilter { } @Document - static class IndexOnMetaAnnotatedField { + class IndexOnMetaAnnotatedField { @Field("_name") @IndexedFieldAnnotation String lastname; } @@ -496,29 +496,29 @@ public void resolveExpressionIndexNameForGeoIndex() { } @Document("Zero") - static class GeoSpatialIndexOnLevelZero { + class GeoSpatialIndexOnLevelZero { @GeoSpatialIndexed Point geoIndexedProperty; } @Document("One") - static class GeoSpatialIndexOnLevelOne { + class GeoSpatialIndexOnLevelOne { GeoSpatialIndexOnLevelZero zero; } @Document("Two") - static class GeoSpatialIndexOnLevelTwo { + class GeoSpatialIndexOnLevelTwo { GeoSpatialIndexOnLevelOne one; } @Document("WithOptionsOnGeoSpatialIndexProperty") - static class WithOptionsOnGeoSpatialIndexProperty { + class WithOptionsOnGeoSpatialIndexProperty { @GeoSpatialIndexed(bits = 2, max = 100, min = 1, type = GeoSpatialIndexType.GEO_2D) // Point location; } @Document("WithComposedAnnotation") - static class GeoSpatialIndexedDocumentWithComposedAnnotation { + class GeoSpatialIndexedDocumentWithComposedAnnotation { @ComposedGeoSpatialIndexed // Point location; @@ -543,7 +543,7 @@ static class GeoSpatialIndexedDocumentWithComposedAnnotation { } @Document - static class GeoIndexWithNameAsExpression { + class GeoIndexWithNameAsExpression { @GeoSpatialIndexed(name = "#{'my' + 1 + 'st'}") Point spelIndexName; } @@ -690,18 +690,17 @@ public void singleIndexWithPartialFilter() { assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "compound_index_with_partial") .containsEntry("unique", true).containsEntry("background", true); assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("partialFilterExpression", - new org.bson.Document().append("bar", new org.bson.Document().append("$exists", true))); + org.bson.Document.parse("{'value': {'$exists': true}}")); } - @Document("CompoundIndexOnLevelOne") - static class CompoundIndexOnLevelOne { + class CompoundIndexOnLevelOne { CompoundIndexOnLevelZero zero; } @Document("CompoundIndexOnLevelZeroWithEmptyIndexDef") - static class CompoundIndexOnLevelOneWithEmptyIndexDefinition { + class CompoundIndexOnLevelOneWithEmptyIndexDefinition { CompoundIndexOnLevelZeroWithEmptyIndexDef zero; } @@ -709,26 +708,26 @@ static class CompoundIndexOnLevelOneWithEmptyIndexDefinition { @Document("CompoundIndexOnLevelZero") @CompoundIndexes({ @CompoundIndex(name = "compound_index", def = "{'foo': 1, 'bar': -1}", background = true, sparse = true, unique = true) }) - static class CompoundIndexOnLevelZero {} + class CompoundIndexOnLevelZero {} @CompoundIndexes({ @CompoundIndex(name = "compound_index", background = true, sparse = true, unique = true) }) - static class CompoundIndexOnLevelZeroWithEmptyIndexDef {} + class CompoundIndexOnLevelZeroWithEmptyIndexDef {} @Document("CompoundIndexOnLevelZero") @CompoundIndex(name = "compound_index", def = "{'foo': 1, 'bar': -1}", background = true, sparse = true, unique = true) - static class SingleCompoundIndex {} + class SingleCompoundIndex {} - static class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {} + class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {} @Document("ComountIndexWithAutogeneratedName") @CompoundIndexes({ @CompoundIndex(useGeneratedName = true, def = "{'foo': 1, 'bar': -1}", background = true, sparse = true, unique = true) }) - static class ComountIndexWithAutogeneratedName {} + class ComountIndexWithAutogeneratedName {} @Document("WithComposedAnnotation") @ComposedCompoundIndex - static class CompoundIndexDocumentWithComposedAnnotation {} + class CompoundIndexDocumentWithComposedAnnotation {} @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) @@ -754,21 +753,21 @@ static class CompoundIndexDocumentWithComposedAnnotation {} @Document @CompoundIndex(name = "#{'cmp' + 2 + 'name'}", def = "{'foo': 1, 'bar': -1}") - static class CompoundIndexWithNameExpression {} + class CompoundIndexWithNameExpression {} @Document @CompoundIndex(def = "#{T(org.bson.Document).parse(\"{ 'foo': 1, 'bar': -1 }\")}") - static class CompoundIndexWithDefExpression {} + class CompoundIndexWithDefExpression {} @Document @CompoundIndex(name = "cmp-idx-one", def = "{'firstname': 1, 'lastname': -1}") @CompoundIndex(name = "cmp-idx-two", def = "{'address.city': -1, 'address.street': 1}") - static class RepeatedCompoundIndex {} + class RepeatedCompoundIndex {} @Document("SingleCompoundIndexWithPartialFilter") @CompoundIndex(name = "compound_index_with_partial", def = "{'foo': 1, 'bar': -1}", background = true, - unique = true, partial = "{'bar': {$exists: true}}") - static class SingleCompoundIndexWithPartialFilter {} + unique = true, partialFilter = "{'value': {'$exists': true}}") + class SingleCompoundIndexWithPartialFilter {} } public static class TextIndexedResolutionTests { @@ -904,7 +903,7 @@ public void shouldResolveComposedAnnotationCorrectly() { } @Document - static class TextIndexOnSinglePropertyInRoot { + class TextIndexOnSinglePropertyInRoot { String foo; @@ -912,13 +911,13 @@ static class TextIndexOnSinglePropertyInRoot { } @Document(collation = "de_AT") - static class TextIndexWithCollation { + class TextIndexWithCollation { @TextIndexed String foo; } @Document - static class TextIndexOnMultiplePropertiesInRoot { + class TextIndexOnMultiplePropertiesInRoot { @TextIndexed String foo; @@ -926,48 +925,48 @@ static class TextIndexOnMultiplePropertiesInRoot { } @Document - static class TextIndexOnNestedRoot { + class TextIndexOnNestedRoot { String bar; @TextIndexed TextIndexOnNested nested; } - static class TextIndexOnNested { + class TextIndexOnNested { String foo; } @Document - static class TextIndexOnNestedWithWeightRoot { + class TextIndexOnNestedWithWeightRoot { @TextIndexed(weight = 5) TextIndexOnNested nested; } @Document - static class TextIndexOnNestedWithMostSpecificValueRoot { + class TextIndexOnNestedWithMostSpecificValueRoot { @TextIndexed(weight = 5) TextIndexOnNestedWithMostSpecificValue nested; } - static class TextIndexOnNestedWithMostSpecificValue { + class TextIndexOnNestedWithMostSpecificValue { String foo; @TextIndexed(weight = 10) String bar; } @Document(language = "spanish") - static class DocumentWithDefaultLanguage { + class DocumentWithDefaultLanguage { @TextIndexed String foo; } @Document - static class DocumentWithLanguageOverrideOnNestedElement { + class DocumentWithLanguageOverrideOnNestedElement { DocumentWithLanguageOverride nested; } @Document - static class DocumentWithLanguageOverride { + class DocumentWithLanguageOverride { @TextIndexed String foo; @@ -975,19 +974,19 @@ static class DocumentWithLanguageOverride { } @Document - static class DocumentWithNoTextIndexPropertyButReservedFieldLanguage { + class DocumentWithNoTextIndexPropertyButReservedFieldLanguage { String language; } @Document - static class DocumentWithNoTextIndexPropertyButReservedFieldLanguageAnnotated { + class DocumentWithNoTextIndexPropertyButReservedFieldLanguageAnnotated { @Field("language") String lang; } @Document - static class DocumentWithOverlappingLanguageProps { + class DocumentWithOverlappingLanguageProps { @TextIndexed String foo; String language; @@ -995,7 +994,7 @@ static class DocumentWithOverlappingLanguageProps { } @Document - static class TextIndexedDocumentWithComposedAnnotation { + class TextIndexedDocumentWithComposedAnnotation { @ComposedTextIndexedAnnotation String foo; String lang; @@ -1284,104 +1283,104 @@ public void hashedIndexAndIndexViaComposedAnnotation() { } @Document - static class MixedIndexRoot { + class MixedIndexRoot { @Indexed String first; NestedGeoIndex nestedGeo; } - static class NestedGeoIndex { + class NestedGeoIndex { @GeoSpatialIndexed Point location; } @Document - static class Outer { + class Outer { @DBRef Inner inner; } @Document - static class Inner { + class Inner { @Indexed Outer outer; } @Document - static class CycleLevelZero { + class CycleLevelZero { @Indexed String indexedProperty; CycleLevelZero cyclicReference; } @Document - static class CycleOnLevelOne { + class CycleOnLevelOne { CycleOnLevelOneReferenced reference; } - static class CycleOnLevelOneReferenced { + class CycleOnLevelOneReferenced { @Indexed String indexedProperty; CycleOnLevelOne cyclicReference; } @Document - public static class CycleStartingInBetween { + static class CycleStartingInBetween { CycleOnLevelOne referenceToCycleStart; } @Document - static class NoCycleButIdenticallyNamedProperties { + class NoCycleButIdenticallyNamedProperties { @Indexed String foo; NoCycleButIdenticallyNamedPropertiesNested reference; } - static class NoCycleButIdenticallyNamedPropertiesNested { + class NoCycleButIdenticallyNamedPropertiesNested { @Indexed String foo; NoCycleButIndenticallNamedPropertiesDeeplyNested deep; } - static class NoCycleButIndenticallNamedPropertiesDeeplyNested { + class NoCycleButIndenticallNamedPropertiesDeeplyNested { @Indexed String foo; } @Document("rules") - static class NoCycleManyPathsToDeepValueObject { + class NoCycleManyPathsToDeepValueObject { private NoCycleLevel3 l3; private NoCycleLevel2 l2; } - static class NoCycleLevel2 { + class NoCycleLevel2 { private NoCycleLevel3 l3; } - static class NoCycleLevel3 { + class NoCycleLevel3 { private ValueObject valueObject; } - static class ValueObject { + class ValueObject { @Indexed private String value; } @Document - static class SimilarityHolingBean { + class SimilarityHolingBean { @Indexed @Field("norm") String normalProperty; @Field("similarityL") private List listOfSimilarilyNamedEntities = null; } - static class SimilaritySibling { + class SimilaritySibling { @Field("similarity") private String similarThoughNotEqualNamedProperty; } @Document - static class MultipleObjectsOfSameType { + class MultipleObjectsOfSameType { SelfCyclingViaCollectionType cycleOne; @@ -1389,7 +1388,7 @@ static class MultipleObjectsOfSameType { } @Document - static class SelfCyclingViaCollectionType { + class SelfCyclingViaCollectionType { List cyclic; @@ -1397,55 +1396,55 @@ static class SelfCyclingViaCollectionType { @Document @CompoundIndex(name = "c_index", def = "{ foo:1, bar:1 }") - static class DocumentWithNamedCompoundIndex { + class DocumentWithNamedCompoundIndex { String property; } @Document - static class DocumentWithNamedIndex { + class DocumentWithNamedIndex { @Indexed(name = "property_index") String property; } - static class TypeWithNamedIndex { + class TypeWithNamedIndex { @Indexed(name = "property_index") String property; } @Document - static class DocumentWithNestedDocumentHavingNamedCompoundIndex { + class DocumentWithNestedDocumentHavingNamedCompoundIndex { DocumentWithNamedCompoundIndex propertyOfTypeHavingNamedCompoundIndex; } @CompoundIndex(name = "c_index", def = "{ foo:1, bar:1 }") - static class TypeWithNamedCompoundIndex { + class TypeWithNamedCompoundIndex { String property; } @Document - static class DocumentWithNestedTypeHavingNamedCompoundIndex { + class DocumentWithNestedTypeHavingNamedCompoundIndex { TypeWithNamedCompoundIndex propertyOfTypeHavingNamedCompoundIndex; } @Document - static class DocumentWithNestedDocumentHavingNamedIndex { + class DocumentWithNestedDocumentHavingNamedIndex { DocumentWithNamedIndex propertyOfTypeHavingNamedIndex; } @Document - static class DocumentWithNestedTypeHavingNamedIndex { + class DocumentWithNestedTypeHavingNamedIndex { TypeWithNamedIndex propertyOfTypeHavingNamedIndex; } @Document - public class MultiplePropertiesOfSameTypeWithMatchingStartLetters { + class MultiplePropertiesOfSameTypeWithMatchingStartLetters { - public class NameComponent { + class NameComponent { @Indexed String component; } @@ -1455,9 +1454,9 @@ public class NameComponent { } @Document - public class MultiplePropertiesOfSameTypeWithMatchingStartLettersOnNestedProperty { + class MultiplePropertiesOfSameTypeWithMatchingStartLettersOnNestedProperty { - public class NameComponent { + class NameComponent { @Indexed String nameLast; @Indexed String name; @@ -1467,39 +1466,39 @@ public class NameComponent { } @Document - public static class OuterDocumentReferingToIndexedPropertyViaDifferentNonCyclingPaths { + static class OuterDocumentReferingToIndexedPropertyViaDifferentNonCyclingPaths { NoCycleButIndenticallNamedPropertiesDeeplyNested path1; AlternatePathToNoCycleButIndenticallNamedPropertiesDeeplyNestedDocument path2; } - public static class AlternatePathToNoCycleButIndenticallNamedPropertiesDeeplyNestedDocument { + static class AlternatePathToNoCycleButIndenticallNamedPropertiesDeeplyNestedDocument { NoCycleButIndenticallNamedPropertiesDeeplyNested propertyWithIndexedStructure; } - static class GenericEntityWrapper { + class GenericEntityWrapper { T entity; } @Document - static class EntityWithGenericTypeWrapperAsElement { + class EntityWithGenericTypeWrapperAsElement { List> listWithGeneircTypeElement; } @Document - static class WithHashedIndexOnId { + class WithHashedIndexOnId { @HashIndexed @Id String id; } @Document - static class WithHashedIndex { + class WithHashedIndex { @HashIndexed String value; } @Document - static class WithHashedIndexAndIndex { + class WithHashedIndexAndIndex { @Indexed // @HashIndexed // @@ -1507,7 +1506,7 @@ static class WithHashedIndexAndIndex { } @Document - static class WithComposedHashedIndexAndIndex { + class WithComposedHashedIndexAndIndex { @ComposedHashIndexed(name = "idx-name") String value; } From f907dbc559572e4b77aeb574c3e7e7e2e115d7b6 Mon Sep 17 00:00:00 2001 From: Jacob Botuck Date: Sun, 10 May 2020 16:46:59 -0500 Subject: [PATCH 0205/1381] DATAMONGO-2285 - Throw BulkOperationException instead of translated one when running bulk operations. Return BulkOperationException unless it is a writeConcernError in which case use existing behavior. Original Pull Request: #862 --- .../core/MongoExceptionTranslator.java | 20 ++++++++-------- .../MongoExceptionTranslatorUnitTests.java | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index e34950375a..cf1a788c62 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -29,6 +29,7 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.dao.PermissionDeniedDataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.data.mongodb.UncategorizedMongoDbException; @@ -39,7 +40,6 @@ import com.mongodb.MongoBulkWriteException; import com.mongodb.MongoException; import com.mongodb.MongoServerException; -import com.mongodb.bulk.BulkWriteError; /** * Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate @@ -49,6 +49,7 @@ * @author Oliver Gierke * @author Michal Vich * @author Christoph Strobl + * @author Jacob Botuck */ public class MongoExceptionTranslator implements PersistenceExceptionTranslator { @@ -63,7 +64,7 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator Collections.singletonList("MongoInternalException")); private static final Set DATA_INTEGRITY_EXCEPTIONS = new HashSet<>( - Arrays.asList("WriteConcernException", "MongoWriteException", "MongoBulkWriteException")); + Arrays.asList("WriteConcernException", "MongoWriteException")); /* * (non-Javadoc) @@ -98,18 +99,17 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) { if (((MongoServerException) ex).getCode() == 11000) { return new DuplicateKeyException(ex.getMessage(), ex); } - if (ex instanceof MongoBulkWriteException) { - for (BulkWriteError x : ((MongoBulkWriteException) ex).getWriteErrors()) { - if (x.getCode() == 11000) { - return new DuplicateKeyException(ex.getMessage(), ex); - } - } - } } return new DataIntegrityViolationException(ex.getMessage(), ex); } - + if (ex instanceof MongoBulkWriteException) { + MongoBulkWriteException mongoBulkWriteException = (MongoBulkWriteException) ex; + if (mongoBulkWriteException.getWriteConcernError() != null) { + return new DataIntegrityViolationException(ex.getMessage(), ex); + } + return new BulkOperationException(ex.getMessage(), mongoBulkWriteException); + } // All other MongoExceptions if (ex instanceof MongoException) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java index 04cd781acd..e9241b81cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java @@ -18,7 +18,12 @@ import static org.assertj.core.api.Assertions.*; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import com.mongodb.MongoBulkWriteException; +import com.mongodb.bulk.BulkWriteError; +import com.mongodb.bulk.WriteConcernError; import org.bson.BsonDocument; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,9 +31,11 @@ import org.springframework.core.NestedRuntimeException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessResourceUsageException; +import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.data.mongodb.UncategorizedMongoDbException; @@ -45,6 +52,7 @@ * @author Michal Vich * @author Oliver Gierke * @author Christoph Strobl + * @author Jacob Botuck */ public class MongoExceptionTranslatorUnitTests { @@ -152,6 +160,22 @@ public void translateTransactionExceptions() { checkTranslatedMongoException(MongoTransactionException.class, 267); } + @Test + public void translateMongoBulkOperationExceptionWithWriteConcernError() { + + expectExceptionWithCauseMessage(translator.translateExceptionIfPossible(new MongoBulkWriteException(null, + new ArrayList<>(), new WriteConcernError(42, "codename", "writeconcern error happened", new BsonDocument()), + new ServerAddress())), DataIntegrityViolationException.class, null); + } + + @Test + public void translateMongoBulkOperationExceptionWithoutWriteConcernError() { + + expectExceptionWithCauseMessage(translator.translateExceptionIfPossible(new MongoBulkWriteException(null, + Arrays.asList(new BulkWriteError(42, "a write error happened", new BsonDocument(), 49)), null, + new ServerAddress())), BulkOperationException.class, null); + } + private void checkTranslatedMongoException(Class clazz, int code) { DataAccessException translated = translator.translateExceptionIfPossible(new MongoException(code, "")); From cee1d976ded5812655855cc078e99bdc7c04ec8b Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 23 Jun 2020 08:37:37 +0200 Subject: [PATCH 0206/1381] DATAMONGO-2285 - Polishing. Preserve existing logic translating com.mongodb.MongoBulkWriteException that might be thrown by calling MongoOperations.insertAll(Collection), and move bulk operation translation to DefaultBulkOperations. Along the lines remove the no longer used PersistenceExceptionTranslator from DefaultBulkOperations. Original Pull Request: #862 --- .../mongodb/core/DefaultBulkOperations.java | 41 +++++++++++-------- .../core/MongoExceptionTranslator.java | 20 ++++----- .../data/mongodb/core/MongoTemplate.java | 1 - ...DefaultBulkOperationsIntegrationTests.java | 9 ++-- .../core/DefaultBulkOperationsUnitTests.java | 31 ++++++++++++++ .../MongoExceptionTranslatorUnitTests.java | 24 ----------- 6 files changed, 70 insertions(+), 56 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index 10518301f2..fb3d3fcf26 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -24,8 +24,9 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.mapping.callback.EntityCallbacks; +import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.convert.UpdateMapper; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -46,6 +47,7 @@ import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; +import com.mongodb.MongoBulkWriteException; import com.mongodb.WriteConcern; import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.MongoCollection; @@ -62,6 +64,7 @@ * @author Jens Schauder * @author Michail Nikolaev * @author Roman Puchkovskiy + * @author Jacob Botuck * @since 1.9 */ class DefaultBulkOperations implements BulkOperations { @@ -71,7 +74,6 @@ class DefaultBulkOperations implements BulkOperations { private final BulkOperationContext bulkOperationContext; private final List models = new ArrayList<>(); - private PersistenceExceptionTranslator exceptionTranslator; private @Nullable WriteConcern defaultWriteConcern; private BulkWriteOptions bulkOptions; @@ -95,19 +97,9 @@ class DefaultBulkOperations implements BulkOperations { this.mongoOperations = mongoOperations; this.collectionName = collectionName; this.bulkOperationContext = bulkOperationContext; - this.exceptionTranslator = new MongoExceptionTranslator(); this.bulkOptions = getBulkWriteOptions(bulkOperationContext.getBulkMode()); } - /** - * Configures the {@link PersistenceExceptionTranslator} to be used. Defaults to {@link MongoExceptionTranslator}. - * - * @param exceptionTranslator can be {@literal null}. - */ - public void setExceptionTranslator(@Nullable PersistenceExceptionTranslator exceptionTranslator) { - this.exceptionTranslator = exceptionTranslator == null ? new MongoExceptionTranslator() : exceptionTranslator; - } - /** * Configures the default {@link WriteConcern} to be used. Defaults to {@literal null}. * @@ -314,11 +306,26 @@ private BulkWriteResult bulkWriteTo(MongoCollection collection) { collection = collection.withWriteConcern(defaultWriteConcern); } - return collection.bulkWrite( // - models.stream() // - .map(this::extractAndMapWriteModel) // - .collect(Collectors.toList()), // - bulkOptions); + try { + + return collection.bulkWrite( // + models.stream() // + .map(this::extractAndMapWriteModel) // + .collect(Collectors.toList()), // + bulkOptions); + } catch (RuntimeException ex) { + + if (ex instanceof MongoBulkWriteException) { + + MongoBulkWriteException mongoBulkWriteException = (MongoBulkWriteException) ex; + if (mongoBulkWriteException.getWriteConcernError() != null) { + throw new DataIntegrityViolationException(ex.getMessage(), ex); + } + throw new BulkOperationException(ex.getMessage(), mongoBulkWriteException); + } + + throw ex; + } } private WriteModel extractAndMapWriteModel(SourceAwareWriteModelHolder it) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index cf1a788c62..e34950375a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -29,7 +29,6 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.dao.PermissionDeniedDataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.data.mongodb.UncategorizedMongoDbException; @@ -40,6 +39,7 @@ import com.mongodb.MongoBulkWriteException; import com.mongodb.MongoException; import com.mongodb.MongoServerException; +import com.mongodb.bulk.BulkWriteError; /** * Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate @@ -49,7 +49,6 @@ * @author Oliver Gierke * @author Michal Vich * @author Christoph Strobl - * @author Jacob Botuck */ public class MongoExceptionTranslator implements PersistenceExceptionTranslator { @@ -64,7 +63,7 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator Collections.singletonList("MongoInternalException")); private static final Set DATA_INTEGRITY_EXCEPTIONS = new HashSet<>( - Arrays.asList("WriteConcernException", "MongoWriteException")); + Arrays.asList("WriteConcernException", "MongoWriteException", "MongoBulkWriteException")); /* * (non-Javadoc) @@ -99,17 +98,18 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) { if (((MongoServerException) ex).getCode() == 11000) { return new DuplicateKeyException(ex.getMessage(), ex); } + if (ex instanceof MongoBulkWriteException) { + for (BulkWriteError x : ((MongoBulkWriteException) ex).getWriteErrors()) { + if (x.getCode() == 11000) { + return new DuplicateKeyException(ex.getMessage(), ex); + } + } + } } return new DataIntegrityViolationException(ex.getMessage(), ex); } - if (ex instanceof MongoBulkWriteException) { - MongoBulkWriteException mongoBulkWriteException = (MongoBulkWriteException) ex; - if (mongoBulkWriteException.getWriteConcernError() != null) { - return new DataIntegrityViolationException(ex.getMessage(), ex); - } - return new BulkOperationException(ex.getMessage(), mongoBulkWriteException); - } + // All other MongoExceptions if (ex instanceof MongoException) { 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 d37c9888af..015cbf25b0 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 @@ -757,7 +757,6 @@ public BulkOperations bulkOps(BulkMode mode, @Nullable Class entityType, Stri new BulkOperationContext(mode, Optional.ofNullable(getPersistentEntity(entityType)), queryMapper, updateMapper, eventPublisher, entityCallbacks)); - operations.setExceptionTranslator(exceptionTranslator); operations.setDefaultWriteConcern(writeConcern); return operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java index 3a04a67a0a..ac0f6e5092 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.dao.DuplicateKeyException; +import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -91,13 +92,13 @@ public void insertOrdered() { assertThat(createBulkOps(BulkMode.ORDERED).insert(documents).execute().getInsertedCount()).isEqualTo(2); } - @Test // DATAMONGO-934 + @Test // DATAMONGO-934, DATAMONGO-2285 public void insertOrderedFails() { List documents = Arrays.asList(newDoc("1"), newDoc("1"), newDoc("2")); assertThatThrownBy(() -> createBulkOps(BulkMode.ORDERED).insert(documents).execute()) // - .isInstanceOf(DuplicateKeyException.class) // + .isInstanceOf(BulkOperationException.class) // .hasCauseInstanceOf(MongoBulkWriteException.class) // .extracting(Throwable::getCause) // .satisfies(it -> { @@ -117,13 +118,13 @@ public void insertUnOrdered() { assertThat(createBulkOps(BulkMode.UNORDERED).insert(documents).execute().getInsertedCount()).isEqualTo(2); } - @Test // DATAMONGO-934 + @Test // DATAMONGO-934, DATAMONGO-2285 public void insertUnOrderedContinuesOnError() { List documents = Arrays.asList(newDoc("1"), newDoc("1"), newDoc("2")); assertThatThrownBy(() -> createBulkOps(BulkMode.UNORDERED).insert(documents).execute()) // - .isInstanceOf(DuplicateKeyException.class) // + .isInstanceOf(BulkOperationException.class) // .hasCauseInstanceOf(MongoBulkWriteException.class) // .extracting(Throwable::getCause) // .satisfies(it -> { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 4b9cd57fcd..7e1356c395 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -24,6 +24,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -40,9 +41,11 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.context.ApplicationEventPublisher; import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.annotation.Id; import org.springframework.data.mapping.callback.EntityCallbacks; +import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; @@ -64,9 +67,13 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; +import com.mongodb.MongoBulkWriteException; import com.mongodb.MongoWriteException; +import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; import com.mongodb.WriteError; +import com.mongodb.bulk.BulkWriteError; +import com.mongodb.bulk.WriteConcernError; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.BulkWriteOptions; @@ -85,6 +92,7 @@ * @author Minsu Kim * @author Jens Schauder * @author Roman Puchkovskiy + * @author Jacob Botuck */ @ExtendWith(MockitoExtension.class) class DefaultBulkOperationsUnitTests { @@ -367,6 +375,29 @@ void shouldRetainNestedArrayPathWithPlaceholdersForMappedEntity() { .isEqualTo(new Document("$set", new Document("items.$.documents.0.the_file_id", "file-id"))); } + @Test // DATAMONGO-2285 + public void translateMongoBulkOperationExceptionWithWriteConcernError() { + + when(collection.bulkWrite(anyList(), any(BulkWriteOptions.class))).thenThrow(new MongoBulkWriteException(null, + Collections.emptyList(), + new WriteConcernError(42, "codename", "writeconcern error happened", new BsonDocument()), new ServerAddress())); + + assertThatExceptionOfType(DataIntegrityViolationException.class) + .isThrownBy(() -> ops.insert(new SomeDomainType()).execute()); + + } + + @Test // DATAMONGO-2285 + public void translateMongoBulkOperationExceptionWithoutWriteConcernError() { + + when(collection.bulkWrite(anyList(), any(BulkWriteOptions.class))).thenThrow(new MongoBulkWriteException(null, + Collections.singletonList(new BulkWriteError(42, "a write error happened", new BsonDocument(), 49)), null, + new ServerAddress())); + + assertThatExceptionOfType(BulkOperationException.class) + .isThrownBy(() -> ops.insert(new SomeDomainType()).execute()); + } + static class OrderTest { String id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java index e9241b81cd..04cd781acd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoExceptionTranslatorUnitTests.java @@ -18,12 +18,7 @@ import static org.assertj.core.api.Assertions.*; import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import com.mongodb.MongoBulkWriteException; -import com.mongodb.bulk.BulkWriteError; -import com.mongodb.bulk.WriteConcernError; import org.bson.BsonDocument; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,11 +26,9 @@ import org.springframework.core.NestedRuntimeException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.data.mongodb.UncategorizedMongoDbException; @@ -52,7 +45,6 @@ * @author Michal Vich * @author Oliver Gierke * @author Christoph Strobl - * @author Jacob Botuck */ public class MongoExceptionTranslatorUnitTests { @@ -160,22 +152,6 @@ public void translateTransactionExceptions() { checkTranslatedMongoException(MongoTransactionException.class, 267); } - @Test - public void translateMongoBulkOperationExceptionWithWriteConcernError() { - - expectExceptionWithCauseMessage(translator.translateExceptionIfPossible(new MongoBulkWriteException(null, - new ArrayList<>(), new WriteConcernError(42, "codename", "writeconcern error happened", new BsonDocument()), - new ServerAddress())), DataIntegrityViolationException.class, null); - } - - @Test - public void translateMongoBulkOperationExceptionWithoutWriteConcernError() { - - expectExceptionWithCauseMessage(translator.translateExceptionIfPossible(new MongoBulkWriteException(null, - Arrays.asList(new BulkWriteError(42, "a write error happened", new BsonDocument(), 49)), null, - new ServerAddress())), BulkOperationException.class, null); - } - private void checkTranslatedMongoException(Class clazz, int code) { DataAccessException translated = translator.translateExceptionIfPossible(new MongoException(code, "")); From d52785533d5795ad760401de75bdf5f8b06fa789 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 25 Jun 2020 11:48:10 +0200 Subject: [PATCH 0207/1381] DATAMONGO-2544 - Updated changelog. --- src/main/resources/changelog.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index f70ce8e4bd..6ce67e24ee 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,28 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.0-M1 (2020-06-25) +---------------------------------------- +* DATAMONGO-2576 - Upgrade to Hibernate Validator 5.4.3. +* DATAMONGO-2574 - GridFSOperations should not override content type. +* DATAMONGO-2572 - Remove usage of Oppressive Language. +* DATAMONGO-2570 - Avoiding unintentional unboxing. +* DATAMONGO-2565 - MongoPersistentEntity.getCollation(...) evaluates document expression instead of collation expression. +* DATAMONGO-2564 - Use standard Spring code of conduct. +* DATAMONGO-2562 - CoroutineCrudRepository findAllBy throwing IncorrectResultSizeDataAccessException when more than 1 result. +* DATAMONGO-2560 - Upgrade MongoDB drivers to 4.0.4. +* DATAMONGO-2558 - Add integration test for RxJava 3 repositories. +* DATAMONGO-2556 - Support countAll() in MongoOperations. +* DATAMONGO-2553 - Reference documentation contains links to removed sections. +* DATAMONGO-2547 - java.lang.IllegalArgumentException: com.mongodb.client.MongoDatabase referenced from a method is not visible from class loader. +* DATAMONGO-2545 - Backwards incompatibilities on @Query. +* DATAMONGO-2544 - Release 3.1 M1 (2020.0.0). +* DATAMONGO-2542 - Don't attempt to map query operator keywords to properties. +* DATAMONGO-2538 - Delombok source files. +* DATAMONGO-2285 - BulkOperations.execute throws DuplicateKeyException. +* DATAMONGO-1569 - Allow partial filter expression usage along with the *...Indexed annotations. + + Changes in version 3.0.1.RELEASE (2020-06-10) --------------------------------------------- * DATAMONGO-2565 - MongoPersistentEntity.getCollation(...) evaluates document expression instead of collation expression. @@ -3061,3 +3083,4 @@ Repository + From a70629697b221240803c8d18544ad10dd2b388d1 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 25 Jun 2020 11:48:19 +0200 Subject: [PATCH 0208/1381] DATAMONGO-2544 - Prepare 3.1 M1 (2020.0.0). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index f50a5f840f..2e547a7fef 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-SNAPSHOT + 2.4.0-M1 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-SNAPSHOT + 2.4.0-M1 4.0.4 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index c42a8a0b93..ca04e4475c 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.0 GA +Spring Data MongoDB 3.1 M1 (2020.0.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -15,3 +15,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 2a66cadaa6b3a856c3ecc14ee1038959b79f907a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 25 Jun 2020 11:48:49 +0200 Subject: [PATCH 0209/1381] DATAMONGO-2544 - Release version 3.1 M1 (2020.0.0). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2e547a7fef..321799e2fa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M1 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a85b081e26..5bed65384f 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M1 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 33014c7c4f..86aacc6cd9 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M1 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ea401d5618..b66304cd22 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M1 ../pom.xml From a6a4a0b3b6210d28a65141982580096e4052f57b Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 25 Jun 2020 11:58:19 +0200 Subject: [PATCH 0210/1381] DATAMONGO-2544 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 321799e2fa..2e547a7fef 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M1 + 3.1.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 5bed65384f..a85b081e26 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M1 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 86aacc6cd9..33014c7c4f 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M1 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index b66304cd22..ea401d5618 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M1 + 3.1.0-SNAPSHOT ../pom.xml From b266bd6febf5a374ee07c4ccf1d820fe31742732 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 25 Jun 2020 11:58:22 +0200 Subject: [PATCH 0211/1381] DATAMONGO-2544 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2e547a7fef..f50a5f840f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-M1 + 2.4.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-M1 + 2.4.0-SNAPSHOT 4.0.4 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 966504dfa631e3ef158436fcd0a9a3dd47b6a522 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 3 Jul 2020 10:10:00 +0200 Subject: [PATCH 0212/1381] DATAMONGO-2490 - Fix dbref fetching during ongoing transaction. Original pull request: #875. --- .../data/mongodb/MongoDatabaseUtils.java | 4 +- .../core/convert/DefaultDbRefResolver.java | 5 ++- .../data/mongodb/core/ClientSessionTests.java | 37 +++++++++++++++++++ .../PersonRepositoryTransactionalTests.java | 20 ++++++++++ 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index 2c7d3903cd..3992861468 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -79,7 +79,7 @@ public static MongoDatabase getDatabase(MongoDatabaseFactory factory, SessionSyn * @param factory the {@link MongoDatabaseFactory} to get the {@link MongoDatabase} from. * @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}. */ - public static MongoDatabase getDatabase(String dbName, MongoDatabaseFactory factory) { + public static MongoDatabase getDatabase(@Nullable String dbName, MongoDatabaseFactory factory) { return doGetMongoDatabase(dbName, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION); } @@ -94,7 +94,7 @@ public static MongoDatabase getDatabase(String dbName, MongoDatabaseFactory fact * @param sessionSynchronization the synchronization to use. Must not be {@literal null}. * @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}. */ - public static MongoDatabase getDatabase(String dbName, MongoDatabaseFactory factory, + public static MongoDatabase getDatabase(@Nullable String dbName, MongoDatabaseFactory factory, SessionSynchronization sessionSynchronization) { return doGetMongoDatabase(dbName, factory, sessionSynchronization); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 45b9e6bb75..f0ee5ba418 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -45,6 +45,7 @@ import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.LazyLoadingException; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.MongoDatabaseUtils; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisStd; @@ -497,7 +498,7 @@ private synchronized Object resolve() { */ protected MongoCollection getCollection(DBRef dbref) { - return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getMongoDatabase(dbref.getDatabaseName()) - : mongoDbFactory.getMongoDatabase()).getCollection(dbref.getCollectionName(), Document.class); + return MongoDatabaseUtils.getDatabase(dbref.getDatabaseName(), mongoDbFactory) + .getCollection(dbref.getCollectionName(), Document.class); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index eac80d7c79..f0b660f2ce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -28,6 +28,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; @@ -51,6 +52,7 @@ public class ClientSessionTests { private static final String DB_NAME = "client-session-tests"; private static final String COLLECTION_NAME = "test"; + private static final String REF_COLLECTION_NAME = "test-with-ref"; static @ReplSetClient MongoClient mongoClient; @@ -148,6 +150,31 @@ public void withAbortedTransaction() { assertThat(template.exists(query(where("id").is(saved.getId())), SomeDoc.class)).isFalse(); } + @Test // DATAMONGO-2490 + public void shouldBeAbleToReadDbRefDuringTransaction() { + + SomeDoc ref = new SomeDoc("ref-1", "da value"); + WithDbRef source = new WithDbRef("source-1", "da source", ref); + + ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + + assertThat(session.getOperationTime()).isNull(); + + session.startTransaction(); + + WithDbRef saved = template.withSession(() -> session).execute(action -> { + + template.save(ref); + template.save(source); + + return template.findOne(query(where("id").is(source.id)), WithDbRef.class); + }); + + assertThat(saved.getSomeDocRef()).isEqualTo(ref); + + session.abortTransaction(); + } + @Data @AllArgsConstructor @org.springframework.data.mongodb.core.mapping.Document(COLLECTION_NAME) @@ -157,4 +184,14 @@ static class SomeDoc { String value; } + @Data + @AllArgsConstructor + @org.springframework.data.mongodb.core.mapping.Document(REF_COLLECTION_NAME) + static class WithDbRef { + + @Id String id; + String value; + @DBRef SomeDoc someDocRef; + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index ad78b59692..e5c08cafc6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; @@ -180,6 +181,25 @@ public void shouldHonorRollback() { assertAfterTransaction(hu).isNotPresent(); } + @Test // DATAMONGO-2490 + public void shouldBeAbleToReadDbRefDuringTransaction() { + + User rat = new User(); + rat.setUsername("rat"); + + template.save(rat); + + Person elene = new Person("Elene", "Cromwyll", 18); + elene.setCoworker(rat); + + repository.save(elene); + + Optional loaded = repository.findById(elene.getId()); + assertThat(loaded).isPresent(); + assertThat(loaded.get().getCoworker()).isNotNull(); + assertThat(loaded.get().getCoworker().getUsername()).isEqualTo(rat.getUsername()); + } + private AfterTransactionAssertion assertAfterTransaction(Person person) { AfterTransactionAssertion assertion = new AfterTransactionAssertion<>(new Persistable() { From 6c8cb9eb85f8a5f48d2c86e618ddb772e5c74149 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jul 2020 15:13:29 +0200 Subject: [PATCH 0213/1381] DATAMONGO-2490 - Polishing. Remove unnecessary code. Reuse session-associated collection when logging to avoid unqualified calls to MongoDbFactory.getMongoDatabase(). Create collection before transaction in test for compatibility with older MongoDB servers. Original pull request: #875. --- .../core/convert/DefaultDbRefResolver.java | 13 +++++++----- .../data/mongodb/core/ClientSessionTests.java | 20 ++++++++++--------- .../PersonRepositoryTransactionalTests.java | 1 + 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index f0ee5ba418..02c9e9c2d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -115,14 +115,16 @@ public Object resolveDbRef(MongoPersistentProperty property, @Nullable DBRef dbr @Override public Document fetch(DBRef dbRef) { + MongoCollection mongoCollection = getCollection(dbRef); + if (LOGGER.isTraceEnabled()) { LOGGER.trace("Fetching DBRef '{}' from {}.{}.", dbRef.getId(), - StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getMongoDatabase().getName(), + StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() + : mongoCollection.getNamespace().getDatabaseName(), dbRef.getCollectionName()); } - StringUtils.hasText(dbRef.getDatabaseName()); - return getCollection(dbRef).find(Filters.eq("_id", dbRef.getId())).first(); + return mongoCollection.find(Filters.eq("_id", dbRef.getId())).first(); } /* @@ -153,15 +155,16 @@ public List bulkFetch(List refs) { } DBRef databaseSource = refs.iterator().next(); + MongoCollection mongoCollection = getCollection(databaseSource); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Bulk fetching DBRefs {} from {}.{}.", ids, StringUtils.hasText(databaseSource.getDatabaseName()) ? databaseSource.getDatabaseName() - : mongoDbFactory.getMongoDatabase().getName(), + : mongoCollection.getNamespace().getDatabaseName(), databaseSource.getCollectionName()); } - List result = getCollection(databaseSource) // + List result = mongoCollection // .find(new Document("_id", new Document("$in", ids))) // .into(new ArrayList<>()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index f0b660f2ce..79c3d8df43 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -42,24 +42,26 @@ import com.mongodb.client.MongoClient; /** + * Integration tests for {@link ClientSession} through {@link MongoTemplate#withSession(ClientSession)}. + * * @author Christoph Strobl * @author Mark Paluch */ @ExtendWith({ MongoClientExtension.class }) @EnableIfReplicaSetAvailable @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") -public class ClientSessionTests { +class ClientSessionTests { private static final String DB_NAME = "client-session-tests"; private static final String COLLECTION_NAME = "test"; private static final String REF_COLLECTION_NAME = "test-with-ref"; - static @ReplSetClient MongoClient mongoClient; + private static @ReplSetClient MongoClient mongoClient; - MongoTemplate template; + private MongoTemplate template; @BeforeEach - public void setUp() { + void setUp() { MongoTestUtils.createOrReplaceCollection(DB_NAME, COLLECTION_NAME, mongoClient); @@ -68,7 +70,7 @@ public void setUp() { } @Test // DATAMONGO-1880 - public void shouldApplyClientSession() { + void shouldApplyClientSession() { ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); @@ -85,7 +87,7 @@ public void shouldApplyClientSession() { } @Test // DATAMONGO-2241 - public void shouldReuseConfiguredInfrastructure() { + void shouldReuseConfiguredInfrastructure() { ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); @@ -101,7 +103,7 @@ public void shouldReuseConfiguredInfrastructure() { } @Test // DATAMONGO-1920 - public void withCommittedTransaction() { + void withCommittedTransaction() { ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); @@ -126,7 +128,7 @@ public void withCommittedTransaction() { } @Test // DATAMONGO-1920 - public void withAbortedTransaction() { + void withAbortedTransaction() { ClientSession session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); @@ -151,7 +153,7 @@ public void withAbortedTransaction() { } @Test // DATAMONGO-2490 - public void shouldBeAbleToReadDbRefDuringTransaction() { + void shouldBeAbleToReadDbRefDuringTransaction() { SomeDoc ref = new SomeDoc("ref-1", "da value"); WithDbRef source = new WithDbRef("source-1", "da source", ref); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index e5c08cafc6..7a893a0d9b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -116,6 +116,7 @@ public void setUp() { public void beforeTransaction() { createOrReplaceCollection(DB_NAME, template.getCollectionName(Person.class), client); + createOrReplaceCollection(DB_NAME, template.getCollectionName(User.class), client); durzo = new Person("Durzo", "Blint", 700); kylar = new Person("Kylar", "Stern", 21); From bf89400182fe4d7a75cb663b55b6d6ded0638765 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 29 Jun 2020 11:18:45 +0200 Subject: [PATCH 0214/1381] DATAMONGO-2571 - Fix regular expression parameter binding for String-based queries. Original pull request: #873. --- .../util/json/ParameterBindingJsonReader.java | 19 +++++++++++++------ .../ParameterBindingJsonReaderUnitTests.java | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index cb3a08804f..22821a63dd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -227,7 +227,7 @@ public BsonType readBsonType() { case REGULAR_EXPRESSION: setCurrentBsonType(BsonType.REGULAR_EXPRESSION); - currentValue = bindableValueFor(token).getValue().toString(); + currentValue = bindableValueFor(token).getValue(); break; case STRING: @@ -363,8 +363,11 @@ private BindableValue bindableValueFor(JsonToken token) { return null; } + boolean isRegularExpression = token.getType().equals(JsonTokenType.REGULAR_EXPRESSION); + BindableValue bindableValue = new BindableValue(); - String tokenValue = String.class.cast(token.getValue()); + String tokenValue = isRegularExpression ? token.getValue(BsonRegularExpression.class).getPattern() + : String.class.cast(token.getValue()); Matcher matcher = PARAMETER_BINDING_PATTERN.matcher(tokenValue); if (token.getType().equals(JsonTokenType.UNQUOTED_STRING)) { @@ -404,8 +407,6 @@ private BindableValue bindableValueFor(JsonToken token) { String computedValue = tokenValue; - - Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(computedValue); while (regexMatcher.find()) { @@ -435,9 +436,15 @@ private BindableValue bindableValueFor(JsonToken token) { computedValue = computedValue.replace(group, nullSafeToString(getBindableValueForIndex(index))); } - bindableValue.setValue(computedValue); - bindableValue.setType(BsonType.STRING); + if (isRegularExpression) { + bindableValue.setValue(new BsonRegularExpression(computedValue)); + bindableValue.setType(BsonType.REGULAR_EXPRESSION); + } else { + + bindableValue.setValue(computedValue); + bindableValue.setType(BsonType.STRING); + } return bindableValue; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 6939add042..a237a54343 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -333,6 +333,22 @@ void evaluatesSpelExpressionDefiningEntireQuery() { new Document("user.supervisor", "wonderwoman")))); } + @Test // DATAMONGO-2571 + public void shouldParseRegexCorrectly() { + + Document target = parse("{ $and: [{'fieldA': {$in: [/ABC.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}"); + assertThat(target) + .isEqualTo(Document.parse("{ $and: [{'fieldA': {$in: [/ABC.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}")); + } + + @Test // DATAMONGO-2571 + public void shouldParseRegexWithPlaceholderCorrectly() { + + Document target = parse("{ $and: [{'fieldA': {$in: [/?0.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}", "ABC"); + assertThat(target) + .isEqualTo(Document.parse("{ $and: [{'fieldA': {$in: [/ABC.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}")); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); From 2026f8729e1ab17caedd445b88dfcd0014f1cc17 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 15 Jul 2020 15:33:10 +0200 Subject: [PATCH 0215/1381] DATAMONGO-2571 - Polishing. Reduce test method visibility for JUnit 5. Original pull request: #873. --- .../util/json/ParameterBindingJsonReaderUnitTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index a237a54343..3b1fb761cb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -334,7 +334,7 @@ void evaluatesSpelExpressionDefiningEntireQuery() { } @Test // DATAMONGO-2571 - public void shouldParseRegexCorrectly() { + void shouldParseRegexCorrectly() { Document target = parse("{ $and: [{'fieldA': {$in: [/ABC.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}"); assertThat(target) @@ -342,7 +342,7 @@ public void shouldParseRegexCorrectly() { } @Test // DATAMONGO-2571 - public void shouldParseRegexWithPlaceholderCorrectly() { + void shouldParseRegexWithPlaceholderCorrectly() { Document target = parse("{ $and: [{'fieldA': {$in: [/?0.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}", "ABC"); assertThat(target) From 6cb89d74525b00cd00a368b0d7f3b38d4b862ea8 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 8 May 2020 09:30:25 +0200 Subject: [PATCH 0216/1381] DATAMONGO-2536 - Add option to skip reading aggregation result. Introduce dedicated AggregationPipeline to encapsulate pipeline stages. Original pull request: #876. --- .../data/mongodb/core/MongoTemplate.java | 12 ++ .../mongodb/core/ReactiveMongoTemplate.java | 13 +- .../mongodb/core/aggregation/Aggregation.java | 28 ++--- .../aggregation/AggregationOperation.java | 4 + .../core/aggregation/AggregationOptions.java | 42 +++++++ .../core/aggregation/AggregationPipeline.java | 111 ++++++++++++++++++ .../core/aggregation/AggregationUpdate.java | 6 +- .../core/aggregation/BucketAutoOperation.java | 7 +- .../core/aggregation/BucketOperation.java | 7 +- .../core/aggregation/CountOperation.java | 7 +- .../DocumentEnhancingOperation.java | 5 + .../core/aggregation/FacetOperation.java | 7 +- .../core/aggregation/GeoNearOperation.java | 7 +- .../aggregation/GraphLookupOperation.java | 7 +- .../core/aggregation/GroupOperation.java | 7 +- .../core/aggregation/LimitOperation.java | 7 +- .../core/aggregation/LookupOperation.java | 7 +- .../core/aggregation/MatchOperation.java | 7 +- .../core/aggregation/MergeOperation.java | 9 +- .../core/aggregation/OutOperation.java | 7 +- .../core/aggregation/ProjectionOperation.java | 7 +- .../core/aggregation/RedactOperation.java | 7 +- .../aggregation/ReplaceRootOperation.java | 5 + .../core/aggregation/SampleOperation.java | 7 +- .../core/aggregation/SkipOperation.java | 7 +- .../aggregation/SortByCountOperation.java | 7 +- .../core/aggregation/SortOperation.java | 7 +- .../core/aggregation/TypedAggregation.java | 2 +- .../core/aggregation/UnsetOperation.java | 9 +- .../core/aggregation/UnwindOperation.java | 9 +- .../core/aggregation/AggregationTests.java | 25 +++- .../aggregation/ReactiveAggregationTests.java | 18 +++ 32 files changed, 366 insertions(+), 51 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java 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 015cbf25b0..1b1ad7d332 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 @@ -62,6 +62,7 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; +import org.springframework.data.mongodb.core.aggregation.AggregationOptions.ResultOptions; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; @@ -2152,6 +2153,17 @@ protected AggregationResults doAggregate(Aggregation aggregation, String aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS); } + if(ResultOptions.SKIP.equals(options.resultOptions())) { + + // toCollection only allowed for $out and $merge if those are the last stages + if(aggregation.getPipeline().isOutOrMerge()) { + aggregateIterable.toCollection(); + } else { + aggregateIterable.first(); + } + return new AggregationResults<>(Collections.emptyList(), new Document()); + } + MongoIterable iterable = aggregateIterable.map(val -> { rawResult.add(val); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 03daa82cb4..4688df6c70 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.bson.BsonValue; @@ -68,6 +69,7 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; +import org.springframework.data.mongodb.core.aggregation.AggregationOptions.ResultOptions; import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; @@ -1004,11 +1006,11 @@ protected Flux aggregate(Aggregation aggregation, String collectionName, } ReadDocumentCallback readCallback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName); - return execute(collectionName, collection -> aggregateAndMap(collection, pipeline, options, readCallback, + return execute(collectionName, collection -> aggregateAndMap(collection, pipeline, () -> aggregation.getPipeline().isOutOrMerge(), options, readCallback, aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() : null)); } - private Flux aggregateAndMap(MongoCollection collection, List pipeline, + private Flux aggregateAndMap(MongoCollection collection, List pipeline, Supplier isOutOrMerge, AggregationOptions options, ReadDocumentCallback readCallback, @Nullable Class inputType) { AggregatePublisher cursor = collection.aggregate(pipeline, Document.class) @@ -1028,6 +1030,13 @@ private Flux aggregateAndMap(MongoCollection collection, List (O) it); + } + return Flux.from(cursor.first()).thenMany(Mono.empty()); + } + return Flux.from(cursor).concatMap(readCallback::doWith); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 9128977411..32c4a441c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -96,7 +96,7 @@ public class Aggregation { public static final AggregationOperationContext DEFAULT_CONTEXT = AggregationOperationRenderer.DEFAULT_CONTEXT; public static final AggregationOptions DEFAULT_OPTIONS = newAggregationOptions().build(); - protected final List operations; + protected final AggregationPipeline pipeline; private final AggregationOptions options; /** @@ -139,7 +139,7 @@ public static AggregationUpdate newUpdate(AggregationOperation... operations) { public Aggregation withOptions(AggregationOptions options) { Assert.notNull(options, "AggregationOptions must not be null."); - return new Aggregation(this.operations, options); + return new Aggregation(this.pipeline.getOperations(), options); } /** @@ -202,26 +202,10 @@ protected Aggregation(List aggregationOperations, Aggregat Assert.notNull(aggregationOperations, "AggregationOperations must not be null!"); Assert.notNull(options, "AggregationOptions must not be null!"); - // check $out/$merge is the last operation if it exists - for (AggregationOperation aggregationOperation : aggregationOperations) { - - if (aggregationOperation instanceof OutOperation && !isLast(aggregationOperation, aggregationOperations)) { - throw new IllegalArgumentException("The $out operator must be the last stage in the pipeline."); - } - - if (aggregationOperation instanceof MergeOperation && !isLast(aggregationOperation, aggregationOperations)) { - throw new IllegalArgumentException("The $merge operator must be the last stage in the pipeline."); - } - } - - this.operations = aggregationOperations; + this.pipeline = new AggregationPipeline(aggregationOperations); this.options = options; } - private boolean isLast(AggregationOperation aggregationOperation, List aggregationOperations) { - return aggregationOperations.indexOf(aggregationOperation) == aggregationOperations.size() - 1; - } - /** * Get the {@link AggregationOptions}. * @@ -718,7 +702,11 @@ public static AggregationOptions.Builder newAggregationOptions() { * @since 2.1 */ public List toPipeline(AggregationOperationContext rootContext) { - return AggregationOperationRenderer.toDocument(operations, rootContext); + return pipeline.toDocuments(rootContext); + } + + public AggregationPipeline getPipeline() { + return pipeline; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java index 2b8a7171e5..e611528e77 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java @@ -54,4 +54,8 @@ public interface AggregationOperation { default List toPipelineStages(AggregationOperationContext context) { return Collections.singletonList(toDocument(context)); } + + default String operator() { + return toDocument(Aggregation.DEFAULT_CONTEXT).keySet().iterator().next(); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 96b199b8c0..aab74a8a62 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -52,6 +52,7 @@ public class AggregationOptions { private final Optional collation; private final Optional comment; private Duration maxTime = Duration.ZERO; + private ResultOptions resultOptions = ResultOptions.READ; /** * Creates a new {@link AggregationOptions}. @@ -219,6 +220,14 @@ public Duration getMaxTime() { return maxTime; } + /** + * @return the {@link ResultOptions} to be used when running the {@link Aggregation}. Never {@literal null}. + * @since 3.0 + */ + public ResultOptions resultOptions() { + return resultOptions; + } + /** * Returns a new potentially adjusted copy for the given {@code aggregationCommandObject} with the configuration * applied. @@ -309,6 +318,7 @@ public static class Builder { private @Nullable Collation collation; private @Nullable String comment; private @Nullable Duration maxTime; + private @Nullable ResultOptions resultOptions; /** * Defines whether to off-load intensive sort-operations to disk. @@ -399,6 +409,20 @@ public Builder maxTime(@Nullable Duration maxTime) { return this; } + /** + * Run the aggregation, but do NOT read the aggregation result from the store.
      + * If the expected result of the aggregation is rather large, eg. when using an {@literal $out} operation, this + * option allows to execute the aggregation without having the cursor return the operation result. + * + * @return this. + * @since 3.0 + */ + public Builder skipOutput() { + + this.resultOptions = ResultOptions.SKIP; + return this; + } + /** * Returns a new {@link AggregationOptions} instance with the given configuration. * @@ -410,8 +434,26 @@ public AggregationOptions build() { if (maxTime != null) { options.maxTime = maxTime; } + if (resultOptions != null) { + options.resultOptions = resultOptions; + } return options; } } + + /** + * @since 3.0 + */ + public enum ResultOptions { + + /** + * Just do it!, and do not read the operation result. + */ + SKIP, + /** + * Read the aggregation result from the cursor. + */ + READ; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java new file mode 100644 index 0000000000..2b7ae7d2dc --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java @@ -0,0 +1,111 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.bson.Document; +import org.springframework.util.Assert; + +/** + * The {@link AggregationPipeline} holds the collection of {@link AggregationOperation aggregation stages}. + * + * @author Christoph Strobl + * @since 3.1 + */ +public class AggregationPipeline { + + private final List pipeline; + + /** + * Create an empty pipeline + */ + public AggregationPipeline() { + this(new ArrayList<>()); + } + + /** + * Create a new pipeline with given {@link AggregationOperation stages}. + * + * @param aggregationOperations must not be {@literal null}. + */ + public AggregationPipeline(List aggregationOperations) { + pipeline = new ArrayList<>(aggregationOperations); + } + + /** + * Append the given {@link AggregationOperation stage} to the pipeline. + * + * @param aggregationOperation must not be {@literal null}. + * @return this. + */ + public AggregationPipeline add(AggregationOperation aggregationOperation) { + + Assert.notNull(aggregationOperation, "AggregationOperation must not be null!"); + + pipeline.add(aggregationOperation); + return this; + } + + /** + * Get the list of {@link AggregationOperation aggregation stages}. + * + * @return never {@literal null}. + */ + public List getOperations() { + return Collections.unmodifiableList(pipeline); + } + + List toDocuments(AggregationOperationContext context) { + + verify(); + return AggregationOperationRenderer.toDocument(pipeline, context); + } + + /** + * @return {@literal true} if the last aggregation stage is either {@literal $out} or {@literal $merge}. + */ + public boolean isOutOrMerge() { + + if (pipeline.isEmpty()) { + return false; + } + + String operator = pipeline.get(pipeline.size() - 1).operator(); + return operator.equals("$out") || operator.equals("$merge"); + } + + void verify() { + + // check $out/$merge is the last operation if it exists + for (AggregationOperation aggregationOperation : pipeline) { + + if (aggregationOperation instanceof OutOperation && !isLast(aggregationOperation)) { + throw new IllegalArgumentException("The $out operator must be the last stage in the pipeline."); + } + + if (aggregationOperation instanceof MergeOperation && !isLast(aggregationOperation)) { + throw new IllegalArgumentException("The $merge operator must be the last stage in the pipeline."); + } + } + } + + private boolean isLast(AggregationOperation aggregationOperation) { + return pipeline.indexOf(aggregationOperation) == pipeline.size() - 1; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index e5dadc8412..6efc28106b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -139,7 +139,7 @@ public AggregationUpdate set(SetOperation setOperation) { setOperation.getFields().forEach(it -> { keysTouched.add(it.getName()); }); - operations.add(setOperation); + pipeline.add(setOperation); return this; } @@ -155,7 +155,7 @@ public AggregationUpdate unset(UnsetOperation unsetOperation) { Assert.notNull(unsetOperation, "UnsetOperation must not be null!"); - operations.add(unsetOperation); + pipeline.add(unsetOperation); keysTouched.addAll(unsetOperation.removedFieldNames()); return this; } @@ -172,7 +172,7 @@ public AggregationUpdate unset(UnsetOperation unsetOperation) { public AggregationUpdate replaceWith(ReplaceWithOperation replaceWithOperation) { Assert.notNull(replaceWithOperation, "ReplaceWithOperation must not be null!"); - operations.add(replaceWithOperation); + pipeline.add(replaceWithOperation); return this; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java index bb7e032efa..22511adb88 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java @@ -106,7 +106,12 @@ public Document toDocument(AggregationOperationContext context) { options.putAll(super.toDocument(context)); - return new Document("$bucketAuto", options); + return new Document(operator(), options); + } + + @Override + public String operator() { + return "$bucketAuto"; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java index 9fb67e624b..17e4dbc6fc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java @@ -103,7 +103,12 @@ public Document toDocument(AggregationOperationContext context) { options.putAll(super.toDocument(context)); - return new Document("$bucket", options); + return new Document(operator(), options); + } + + @Override + public String operator() { + return "$bucket"; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java index 4306e7630a..03bdf21caf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java @@ -49,7 +49,12 @@ public CountOperation(String fieldName) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$count", fieldName); + return new Document(operator(), fieldName); + } + + @Override + public String operator() { + return "$count"; } /* (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java index 1562bce705..77a1a064ae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java @@ -71,6 +71,11 @@ public Document toDocument(AggregationOperationContext context) { */ protected abstract String mongoOperator(); + @Override + public String operator() { + return mongoOperator(); + } + /** * @return the raw value map */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java index ea020d2597..e1a4f91441 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java @@ -84,7 +84,12 @@ public FacetOperationBuilder and(AggregationOperation... operations) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$facet", facets.toDocument(context)); + return new Document(operator(), facets.toDocument(context)); + } + + @Override + public String operator() { + return "$facet"; } /* (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java index ca2eaf782f..b17b90d2f0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java @@ -109,7 +109,12 @@ public Document toDocument(AggregationOperationContext context) { command.put("key", indexKey); } - return new Document("$geoNear", command); + return new Document(operator(), command); + } + + @Override + public String operator() { + return "$geoNear"; } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java index dc047ab874..4afb131779 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java @@ -119,7 +119,12 @@ public Document toDocument(AggregationOperationContext context) { graphLookup.put("restrictSearchWithMatch", context.getMappedObject(restrictSearchWithMatch.getCriteriaObject())); } - return new Document("$graphLookup", graphLookup); + return new Document(operator(), graphLookup); + } + + @Override + public String operator() { + return "$graphLookup"; } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index d3efbd299c..d4a4a9dd3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -429,7 +429,12 @@ public Document toDocument(AggregationOperationContext context) { operationObject.putAll(operation.toDocument(context)); } - return new Document("$group", operationObject); + return new Document(operator(), operationObject); + } + + @Override + public String operator() { + return "$group"; } interface Keyword { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java index 67b19c53fa..bc0a0de8ea 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java @@ -49,6 +49,11 @@ public LimitOperation(long maxElements) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$limit", Long.valueOf(maxElements)); + return new Document(operator(), Long.valueOf(maxElements)); + } + + @Override + public String operator() { + return "$limit"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java index cddd94d254..4f2c89c0d4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java @@ -83,7 +83,12 @@ public Document toDocument(AggregationOperationContext context) { lookupObject.append("foreignField", foreignField.getTarget()); lookupObject.append("as", as.getTarget()); - return new Document("$lookup", lookupObject); + return new Document(operator(), lookupObject); + } + + @Override + public String operator() { + return "$lookup"; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index 604ffab2c2..d306077c29 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -53,6 +53,11 @@ public MatchOperation(CriteriaDefinition criteriaDefinition) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$match", context.getMappedObject(criteriaDefinition.getCriteriaObject())); + return new Document(operator(), context.getMappedObject(criteriaDefinition.getCriteriaObject())); + } + + @Override + public String operator() { + return "$match"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java index b052874953..eba2d204b7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java @@ -100,7 +100,7 @@ public static MergeOperationBuilder builder() { public Document toDocument(AggregationOperationContext context) { if (isJustCollection()) { - return new Document("$merge", into.collection); + return new Document(operator(), into.collection); } Document $merge = new Document(); @@ -122,7 +122,12 @@ public Document toDocument(AggregationOperationContext context) { $merge.putAll(whenNotMatched.toDocument(context)); } - return new Document("$merge", $merge); + return new Document(operator(), $merge); + } + + @Override + public String operator() { + return "$merge"; } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java index 11d6407b60..d4c44a1f75 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java @@ -211,7 +211,12 @@ public Document toDocument(AggregationOperationContext context) { $out.append("uniqueKey", uniqueKey); } - return new Document("$out", $out); + return new Document(operator(), $out); + } + + @Override + public String operator() { + return "$out"; } private boolean requiresMongoDb42Format() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index a0ad3b46ff..d0bbcfa061 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -261,7 +261,12 @@ public Document toDocument(AggregationOperationContext context) { fieldObject.putAll(projection.toDocument(context)); } - return new Document("$project", fieldObject); + return new Document(operator(), fieldObject); + } + + @Override + public String operator() { + return "$project"; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java index 2bc77d3580..7f27bf77aa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java @@ -74,7 +74,12 @@ public RedactOperation(AggregationExpression condition) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$redact", condition.toDocument(context)); + return new Document(operator(), condition.toDocument(context)); + } + + @Override + public String operator() { + return "$redact"; } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index e109d78484..6d53221f9f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -86,6 +86,11 @@ public Document toDocument(AggregationOperationContext context) { return new Document("$replaceRoot", new Document("newRoot", getReplacement().toDocumentExpression(context))); } + @Override + public String operator() { + return "$replaceRoot"; + } + /* (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java index a3de07be17..a7c1fe7114 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java @@ -48,6 +48,11 @@ public SampleOperation(long sampleSize) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$sample", new Document("size", this.sampleSize)); + return new Document(operator(), new Document("size", this.sampleSize)); + } + + @Override + public String operator() { + return "$sample"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java index a6c20e61c6..10883b037b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java @@ -51,6 +51,11 @@ public SkipOperation(long skipCount) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$skip", skipCount); + return new Document(operator(), skipCount); + } + + @Override + public String operator() { + return "$skip"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java index 436bb3ab99..f26e60eace 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java @@ -74,7 +74,12 @@ public SortByCountOperation(AggregationExpression groupByExpression) { @Override public Document toDocument(AggregationOperationContext context) { - return new Document("$sortByCount", groupByExpression == null ? context.getReference(groupByField).toString() + return new Document(operator(), groupByExpression == null ? context.getReference(groupByField).toString() : groupByExpression.toDocument(context)); } + + @Override + public String operator() { + return "$sortByCount"; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java index cd3169e4f3..cfd3f8a3e9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java @@ -74,6 +74,11 @@ public Document toDocument(AggregationOperationContext context) { object.put(reference.getRaw(), order.isAscending() ? 1 : -1); } - return new Document("$sort", object); + return new Document(operator(), object); + } + + @Override + public String operator() { + return "$sort"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java index 19427df08c..7c7fbb1c67 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java @@ -81,6 +81,6 @@ public Class getInputType() { public TypedAggregation withOptions(AggregationOptions options) { Assert.notNull(options, "AggregationOptions must not be null."); - return new TypedAggregation(inputType, operations, options); + return new TypedAggregation(inputType, pipeline.getOperations(), options); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java index abd62c5b56..89dc79ea8f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java @@ -117,13 +117,18 @@ Collection removedFieldNames() { public Document toDocument(AggregationOperationContext context) { if (fields.size() == 1) { - return new Document("$unset", computeFieldName(fields.iterator().next(), context)); + return new Document(operator(), computeFieldName(fields.iterator().next(), context)); } - return new Document("$unset", + return new Document(operator(), fields.stream().map(it -> computeFieldName(it, context)).collect(Collectors.toList())); } + @Override + public String operator() { + return "$unset"; + } + private Object computeFieldName(Object field, AggregationOperationContext context) { if (field instanceof Field) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java index 7bb36f9999..492afd2448 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java @@ -94,7 +94,7 @@ public Document toDocument(AggregationOperationContext context) { String path = context.getReference(field).toString(); if (!preserveNullAndEmptyArrays && arrayIndex == null) { - return new Document("$unwind", path); + return new Document(operator(), path); } Document unwindArgs = new Document(); @@ -104,7 +104,12 @@ public Document toDocument(AggregationOperationContext context) { } unwindArgs.put("preserveNullAndEmptyArrays", preserveNullAndEmptyArrays); - return new Document("$unwind", unwindArgs); + return new Document(operator(), unwindArgs); + } + + @Override + public String operator() { + return "$unwind"; } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index 33e9fdb342..6be58d731d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -1625,12 +1625,12 @@ private void createPersonDocuments() { mongoTemplate.save(new Person("Leoniv", "Yakubov", 55, Person.Sex.MALE)); } - @Test // DATAMONGO-1418 + @Test // DATAMONGO-1418, DATAMONGO-2536 public void outShouldOutBeTheLastOperation() { assertThatIllegalArgumentException().isThrownBy(() -> newAggregation(match(new Criteria()), // group("field1").count().as("totalCount"), // out("collection1"), // - skip(100L))); + skip(100L)).toPipeline(DEFAULT_CONTEXT)); } @Test // DATAMONGO-1325 @@ -1907,6 +1907,27 @@ public void shouldReadComplexIdValueCorrectly() { assertThat(result.getMappedResults()).containsOnly(source); } + @Test // DATAMONGO-2536 + public void skipOutputDoesNotReadBackAggregationResults() { + + createTagDocuments(); + + Aggregation agg = newAggregation( // + project("tags"), // + unwind("tags"), // + group("tags") // + .count().as("n"), // + project("n") // + .and("tag").previousOperation(), // + sort(DESC, "n") // + ).withOptions(AggregationOptions.builder().skipOutput().build()); + + AggregationResults results = mongoTemplate.aggregate(agg, INPUT_COLLECTION, TagCount.class); + + assertThat(results.getMappedResults()).isEmpty(); + assertThat(results.getRawResults()).isEmpty(); + } + private void createUsersWithReferencedPersons() { mongoTemplate.dropCollection(User.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java index 262750e631..61d3834b40 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java @@ -164,4 +164,22 @@ public void runMatchOperationCriteriaThroughQueryMapperForUntypedAggregation() { reactiveMongoTemplate.aggregate(aggregation, "newyork", Document.class).as(StepVerifier::create).expectNextCount(4) .verifyComplete(); } + + @Test // DATAMONGO-2356 + public void skipOutputDoesNotReadBackAggregationResults() { + + Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); + reactiveMongoTemplate.insert(product).as(StepVerifier::create).expectNextCount(1).verifyComplete(); + + double shippingCosts = 1.2; + + TypedAggregation agg = newAggregation(Product.class, // + project("name", "netPrice") // + .andExpression("netPrice * 10", shippingCosts).as("salesPrice") // + ).withOptions(AggregationOptions.builder().skipOutput().build()); + + reactiveMongoTemplate.aggregate(agg, Document.class).as(StepVerifier::create).verifyComplete(); + } + + } From 2c1a3cf03e85fb8d1af3d5464837412f6bc368fc Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 16 Jul 2020 09:41:46 +0200 Subject: [PATCH 0217/1381] DATAMONGO-2536 - Polishing. Encapsulate skipResults in AggregationOptions. Reformat code. Add override Javadoc. Original pull request: #876. --- .../data/mongodb/core/MongoTemplate.java | 8 +- .../mongodb/core/ReactiveMongoTemplate.java | 19 +-- .../core/aggregation/AddFieldsOperation.java | 4 + .../mongodb/core/aggregation/Aggregation.java | 8 +- .../aggregation/AggregationOperation.java | 9 +- .../core/aggregation/AggregationOptions.java | 13 +- .../core/aggregation/AggregationPipeline.java | 4 +- .../core/aggregation/BucketAutoOperation.java | 11 +- .../core/aggregation/BucketOperation.java | 20 ++- .../core/aggregation/CountOperation.java | 4 +- .../DocumentEnhancingOperation.java | 6 +- .../core/aggregation/FacetOperation.java | 11 +- .../core/aggregation/GeoNearOperation.java | 21 ++- .../aggregation/GraphLookupOperation.java | 4 +- .../core/aggregation/GroupOperation.java | 8 +- .../core/aggregation/LimitOperation.java | 8 +- .../core/aggregation/LiteralOperators.java | 4 + .../core/aggregation/LookupOperation.java | 11 +- .../core/aggregation/MatchOperation.java | 11 +- .../core/aggregation/MergeOperation.java | 10 +- .../core/aggregation/OutOperation.java | 9 +- .../core/aggregation/ProjectionOperation.java | 14 +- .../core/aggregation/RedactOperation.java | 8 +- .../aggregation/ReplaceRootOperation.java | 6 +- .../core/aggregation/SampleOperation.java | 8 +- .../core/aggregation/SetOperation.java | 4 + .../core/aggregation/SkipOperation.java | 11 +- .../aggregation/SortByCountOperation.java | 10 +- .../core/aggregation/SortOperation.java | 11 +- .../core/aggregation/UnsetOperation.java | 12 +- .../core/aggregation/UnwindOperation.java | 13 +- .../core/aggregation/AggregationTests.java | 160 +++++++++--------- .../aggregation/ReactiveAggregationTests.java | 1 - 33 files changed, 278 insertions(+), 183 deletions(-) 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 1b1ad7d332..acdcfd7a98 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 @@ -28,6 +28,7 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -62,7 +63,6 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; -import org.springframework.data.mongodb.core.aggregation.AggregationOptions.ResultOptions; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; @@ -2132,7 +2132,7 @@ protected AggregationResults doAggregate(Aggregation aggregation, String List rawResult = new ArrayList<>(); - Class domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() + Class domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() : null; Optional collation = Optionals.firstNonEmpty(options::getCollation, @@ -2153,10 +2153,10 @@ protected AggregationResults doAggregate(Aggregation aggregation, String aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS); } - if(ResultOptions.SKIP.equals(options.resultOptions())) { + if (options.isSkipResults()) { // toCollection only allowed for $out and $merge if those are the last stages - if(aggregation.getPipeline().isOutOrMerge()) { + if (aggregation.getPipeline().isOutOrMerge()) { aggregateIterable.toCollection(); } else { aggregateIterable.first(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 4688df6c70..da60cd671c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.bson.BsonValue; @@ -37,6 +36,7 @@ import org.reactivestreams.Subscriber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -69,7 +69,6 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; -import org.springframework.data.mongodb.core.aggregation.AggregationOptions.ResultOptions; import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; @@ -1006,11 +1005,14 @@ protected Flux aggregate(Aggregation aggregation, String collectionName, } ReadDocumentCallback readCallback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName); - return execute(collectionName, collection -> aggregateAndMap(collection, pipeline, () -> aggregation.getPipeline().isOutOrMerge(), options, readCallback, - aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() : null)); + return execute(collectionName, + collection -> aggregateAndMap(collection, pipeline, aggregation.getPipeline().isOutOrMerge(), options, + readCallback, + aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() : null)); } - private Flux aggregateAndMap(MongoCollection collection, List pipeline, Supplier isOutOrMerge, + private Flux aggregateAndMap(MongoCollection collection, List pipeline, + boolean isOutOrMerge, AggregationOptions options, ReadDocumentCallback readCallback, @Nullable Class inputType) { AggregatePublisher cursor = collection.aggregate(pipeline, Document.class) @@ -1030,11 +1032,8 @@ private Flux aggregateAndMap(MongoCollection collection, List (O) it); - } - return Flux.from(cursor.first()).thenMany(Mono.empty()); + if (options.isSkipResults()) { + return (isOutOrMerge ? Flux.from(cursor.toCollection()) : Flux.from(cursor.first())).thenMany(Mono.empty()); } return Flux.from(cursor).concatMap(readCallback::doWith); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java index 8ebc744adf..449c137b7e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java @@ -99,6 +99,10 @@ public AddFieldsOperationBuilder and() { return new AddFieldsOperationBuilder(getValueMap()); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.DocumentEnhancingOperation#mongoOperator() + */ @Override protected String mongoOperator() { return "$addFields"; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 32c4a441c4..df75781255 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -645,9 +645,9 @@ public static CountOperationBuilder count() { /** * Creates a new {@link RedactOperation} that can restrict the content of a document based on information stored * within the document itself. - * + * *
      -	 * 
      +	 *
       	 * Aggregation.redact(ConditionalOperators.when(Criteria.where("level").is(5)) //
       	 * 		.then(RedactOperation.PRUNE) //
       	 * 		.otherwise(RedactOperation.DESCEND));
      @@ -705,6 +705,10 @@ public List toPipeline(AggregationOperationContext rootContext) {
       		return pipeline.toDocuments(rootContext);
       	}
       
      +	/**
      +	 * @return the {@link AggregationPipeline}.
      +	 * @since 3.0.2
      +	 */
       	public AggregationPipeline getPipeline() {
       		return pipeline;
       	}
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java
      index e611528e77..b22458ad94 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java
      @@ -55,7 +55,14 @@ default List toPipelineStages(AggregationOperationContext context) {
       		return Collections.singletonList(toDocument(context));
       	}
       
      -	default String operator() {
      +	/**
      +	 * Return the MongoDB operator that is used for this {@link AggregationOperation}. Aggregation operations should
      +	 * implement this method to avoid document rendering.
      +	 *
      +	 * @return the operator used for this {@link AggregationOperation}.
      +	 * @since 3.0.2
      +	 */
      +	default String getOperator() {
       		return toDocument(Aggregation.DEFAULT_CONTEXT).keySet().iterator().next();
       	}
       }
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java
      index aab74a8a62..fc59282156 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java
      @@ -221,11 +221,12 @@ public Duration getMaxTime() {
       	}
       
       	/**
      -	 * @return the {@link ResultOptions} to be used when running the {@link Aggregation}. Never {@literal null}.
      -	 * @since 3.0
      +	 * @return {@literal true} to skip results when running an aggregation. Useful in combination with {@code $merge} or
      +	 *         {@code $out}.
      +	 * @since 3.0.2
       	 */
      -	public ResultOptions resultOptions() {
      -		return resultOptions;
      +	public boolean isSkipResults() {
      +		return ResultOptions.SKIP.equals(resultOptions);
       	}
       
       	/**
      @@ -415,7 +416,7 @@ public Builder maxTime(@Nullable Duration maxTime) {
       		 * option allows to execute the aggregation without having the cursor return the operation result.
       		 *
       		 * @return this.
      -		 * @since 3.0
      +		 * @since 3.0.2
       		 */
       		public Builder skipOutput() {
       
      @@ -445,7 +446,7 @@ public AggregationOptions build() {
       	/**
       	 * @since 3.0
       	 */
      -	public enum ResultOptions {
      +	private enum ResultOptions {
       
       		/**
       		 * Just do it!, and do not read the operation result.
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java
      index 2b7ae7d2dc..8c4b0ed10d 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java
      @@ -26,7 +26,7 @@
        * The {@link AggregationPipeline} holds the collection of {@link AggregationOperation aggregation stages}.
        *
        * @author Christoph Strobl
      - * @since 3.1
      + * @since 3.0.2
        */
       public class AggregationPipeline {
       
      @@ -86,7 +86,7 @@ public boolean isOutOrMerge() {
       			return false;
       		}
       
      -		String operator = pipeline.get(pipeline.size() - 1).operator();
      +		String operator = pipeline.get(pipeline.size() - 1).getOperator();
       		return operator.equals("$out") || operator.equals("$merge");
       	}
       
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java
      index 22511adb88..3f2d733470 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java
      @@ -15,12 +15,11 @@
        */
       package org.springframework.data.mongodb.core.aggregation;
       
      +import org.bson.Document;
       import org.springframework.data.mongodb.core.aggregation.BucketAutoOperation.BucketAutoOperationOutputBuilder;
       import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.OutputBuilder;
       import org.springframework.util.Assert;
       
      -import org.bson.Document;
      -
       /**
        * Encapsulates the aggregation framework {@code $bucketAuto}-operation. 
      * Bucket stage is typically used with {@link Aggregation} and {@code $facet}. Categorizes incoming documents into a @@ -106,11 +105,15 @@ public Document toDocument(AggregationOperationContext context) { options.putAll(super.toDocument(context)); - return new Document(operator(), options); + return new Document(getOperator(), options); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$bucketAuto"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java index 17e4dbc6fc..67cdbe2ee5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java @@ -20,21 +20,19 @@ import java.util.Collections; import java.util.List; +import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.BucketOperation.BucketOperationOutputBuilder; import org.springframework.util.Assert; -import org.bson.Document; - /** * Encapsulates the aggregation framework {@code $bucket}-operation.
      - * * Bucket stage is typically used with {@link Aggregation} and {@code $facet}. Categorizes incoming documents into * groups, called buckets, based on a specified expression and bucket boundaries.
      - * * We recommend to use the static factory method {@link Aggregation#bucket(String)} instead of creating instances of * this class directly. * - * @see https://docs.mongodb.org/manual/reference/aggregation/bucket/ + * @see https://docs.mongodb.org/manual/reference/aggregation/bucket/ * @see BucketOperationSupport * @author Mark Paluch * @since 1.10 @@ -103,11 +101,15 @@ public Document toDocument(AggregationOperationContext context) { options.putAll(super.toDocument(context)); - return new Document(operator(), options); + return new Document(getOperator(), options); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$bucket"; } @@ -209,8 +211,8 @@ public static class ExpressionBucketOperationBuilder extends ExpressionBucketOperationBuilderSupport { /** - * Creates a new {@link ExpressionBucketOperationBuilderSupport} for the given value, {@link BucketOperation} - * and parameters. + * Creates a new {@link ExpressionBucketOperationBuilderSupport} for the given value, {@link BucketOperation} and + * parameters. * * @param expression must not be {@literal null}. * @param operation must not be {@literal null}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java index 03bdf21caf..8ac0d45b62 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java @@ -49,11 +49,11 @@ public CountOperation(String fieldName) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), fieldName); + return new Document(getOperator(), fieldName); } @Override - public String operator() { + public String getOperator() { return "$count"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java index 77a1a064ae..0a650dc0dc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java @@ -71,8 +71,12 @@ public Document toDocument(AggregationOperationContext context) { */ protected abstract String mongoOperator(); + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return mongoOperator(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java index e1a4f91441..77fe14854d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java @@ -20,12 +20,11 @@ import java.util.Collections; import java.util.List; +import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.Output; import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; import org.springframework.util.Assert; -import org.bson.Document; - /** * Encapsulates the aggregation framework {@code $facet}-operation.
      * Facet of {@link AggregationOperation}s to be used in an {@link Aggregation}. Processes multiple @@ -84,11 +83,15 @@ public FacetOperationBuilder and(AggregationOperation... operations) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), facets.toDocument(context)); + return new Document(getOperator(), facets.toDocument(context)); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$facet"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java index b17b90d2f0..83468abb1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java @@ -16,14 +16,12 @@ package org.springframework.data.mongodb.core.aggregation; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.bson.Document; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.util.NumberUtils; import org.springframework.util.StringUtils; /** @@ -95,25 +93,26 @@ public Document toDocument(AggregationOperationContext context) { Document command = context.getMappedObject(nearQuery.toDocument()); - if(command.containsKey("query")) { + if (command.containsKey("query")) { command.replace("query", context.getMappedObject(command.get("query", Document.class))); } - if(command.containsKey("collation")) { - command.remove("collation"); - } - + command.remove("collation"); command.put("distanceField", distanceField); if (StringUtils.hasText(indexKey)) { command.put("key", indexKey); } - return new Document(operator(), command); + return new Document(getOperator(), command); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$geoNear"; } @@ -130,11 +129,11 @@ public List toPipelineStages(AggregationOperationContext context) { List stages = new ArrayList<>(); stages.add(command); - if(nearQuery.getSkip() != null && nearQuery.getSkip() > 0){ + if (nearQuery.getSkip() != null && nearQuery.getSkip() > 0) { stages.add(new Document("$skip", nearQuery.getSkip())); } - if(limit != null) { + if (limit != null) { stages.add(new Document("$limit", limit.longValue())); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java index 4afb131779..abf7ff393c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java @@ -119,11 +119,11 @@ public Document toDocument(AggregationOperationContext context) { graphLookup.put("restrictSearchWithMatch", context.getMappedObject(restrictSearchWithMatch.getCriteriaObject())); } - return new Document(operator(), graphLookup); + return new Document(getOperator(), graphLookup); } @Override - public String operator() { + public String getOperator() { return "$graphLookup"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index d4a4a9dd3a..8f586fd754 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -429,11 +429,15 @@ public Document toDocument(AggregationOperationContext context) { operationObject.putAll(operation.toDocument(context)); } - return new Document(operator(), operationObject); + return new Document(getOperator(), operationObject); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$group"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java index bc0a0de8ea..e41363b233 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java @@ -49,11 +49,15 @@ public LimitOperation(long maxElements) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), Long.valueOf(maxElements)); + return new Document(getOperator(), Long.valueOf(maxElements)); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$limit"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java index 64ac1a1d26..062f823e37 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java @@ -76,6 +76,10 @@ private Literal(Object value) { super(value); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AbstractAggregationExpression#getMongoMethod() + */ @Override protected String getMongoMethod() { return "$literal"; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java index 4f2c89c0d4..7be63c33ee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java @@ -83,11 +83,15 @@ public Document toDocument(AggregationOperationContext context) { lookupObject.append("foreignField", foreignField.getTarget()); lookupObject.append("as", as.getTarget()); - return new Document(operator(), lookupObject); + return new Document(getOperator(), lookupObject); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$lookup"; } @@ -173,8 +177,7 @@ public LookupOperation as(String name) { Assert.hasText(name, "'As' must not be null or empty!"); as = new ExposedField(Fields.field(name), true); - return new LookupOperation(from, localField, foreignField, - as); + return new LookupOperation(from, localField, foreignField, as); } @Override diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index d306077c29..8f2f0aa288 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -30,7 +30,8 @@ * @author Thomas Darimont * @author Oliver Gierke * @since 1.3 - * @see MongoDB Aggregation Framework: $match + * @see MongoDB Aggregation Framework: + * $match */ public class MatchOperation implements AggregationOperation { @@ -53,11 +54,15 @@ public MatchOperation(CriteriaDefinition criteriaDefinition) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), context.getMappedObject(criteriaDefinition.getCriteriaObject())); + return new Document(getOperator(), context.getMappedObject(criteriaDefinition.getCriteriaObject())); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$match"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java index eba2d204b7..05e01e4fcf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java @@ -100,7 +100,7 @@ public static MergeOperationBuilder builder() { public Document toDocument(AggregationOperationContext context) { if (isJustCollection()) { - return new Document(operator(), into.collection); + return new Document(getOperator(), into.collection); } Document $merge = new Document(); @@ -122,11 +122,15 @@ public Document toDocument(AggregationOperationContext context) { $merge.putAll(whenNotMatched.toDocument(context)); } - return new Document(operator(), $merge); + return new Document(getOperator(), $merge); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$merge"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java index d4c44a1f75..4eaa669667 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.core.aggregation; import org.bson.Document; - import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -211,11 +210,15 @@ public Document toDocument(AggregationOperationContext context) { $out.append("uniqueKey", uniqueKey); } - return new Document(operator(), $out); + return new Document(getOperator(), $out); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$out"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index d0bbcfa061..21278041ae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -261,11 +261,15 @@ public Document toDocument(AggregationOperationContext context) { fieldObject.putAll(projection.toDocument(context)); } - return new Document(operator(), fieldObject); + return new Document(getOperator(), fieldObject); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$project"; } @@ -1553,7 +1557,7 @@ OperationProjection withAlias(String alias) { final Field aliasedField = Fields.field(alias, this.field.getName()); return new OperationProjection(aliasedField, operation, values.toArray()) { - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder.OperationProjection#getField() */ @@ -1754,7 +1758,7 @@ public ExpressionProjection(Field field, AggregationExpression expression) { this.expression = expression; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) */ @@ -1882,7 +1886,7 @@ public ArrayProjection(Field targetField, List projections) { this.projections = projections; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java index 7f27bf77aa..3428b64bbc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java @@ -74,11 +74,15 @@ public RedactOperation(AggregationExpression condition) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), condition.toDocument(context)); + return new Document(getOperator(), condition.toDocument(context)); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$redact"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index 6d53221f9f..a63275feef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -86,8 +86,12 @@ public Document toDocument(AggregationOperationContext context) { return new Document("$replaceRoot", new Document("newRoot", getReplacement().toDocumentExpression(context))); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$replaceRoot"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java index a7c1fe7114..b1c3bf4ceb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java @@ -48,11 +48,15 @@ public SampleOperation(long sampleSize) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), new Document("size", this.sampleSize)); + return new Document(getOperator(), new Document("size", this.sampleSize)); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$sample"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index b9f43d5d3f..cd06098fe6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -99,6 +99,10 @@ public FieldAppender and() { return new FieldAppender(getValueMap()); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.DocumentEnhancingOperation#mongoOperator() + */ @Override protected String mongoOperator() { return "$set"; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java index 10883b037b..2fbbc7209e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java @@ -28,7 +28,8 @@ * @author Oliver Gierke * @author Christoph Strobl * @since 1.3 - * @see MongoDB Aggregation Framework: $skip + * @see MongoDB Aggregation Framework: + * $skip */ public class SkipOperation implements AggregationOperation { @@ -51,11 +52,15 @@ public SkipOperation(long skipCount) { */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), skipCount); + return new Document(getOperator(), skipCount); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$skip"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java index f26e60eace..a631b08627 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java @@ -67,19 +67,23 @@ public SortByCountOperation(AggregationExpression groupByExpression) { this.groupByField = null; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) */ @Override public Document toDocument(AggregationOperationContext context) { - return new Document(operator(), groupByExpression == null ? context.getReference(groupByField).toString() + return new Document(getOperator(), groupByExpression == null ? context.getReference(groupByField).toString() : groupByExpression.toDocument(context)); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$sortByCount"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java index cfd3f8a3e9..5b5cce4588 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java @@ -33,7 +33,8 @@ * @author Christoph Strobl * @author Mark Paluch * @since 1.3 - * @see MongoDB Aggregation Framework: $sort + * @see MongoDB Aggregation Framework: + * $sort */ public class SortOperation implements AggregationOperation { @@ -74,11 +75,15 @@ public Document toDocument(AggregationOperationContext context) { object.put(reference.getRaw(), order.isAscending() ? 1 : -1); } - return new Document(operator(), object); + return new Document(getOperator(), object); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$sort"; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java index 89dc79ea8f..b42cef2a69 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java @@ -40,7 +40,7 @@ public class UnsetOperation implements InheritsFieldsAggregationOperation { /** * Create new instance of {@link UnsetOperation}. - * + * * @param fields must not be {@literal null}. */ public UnsetOperation(Collection fields) { @@ -117,15 +117,19 @@ Collection removedFieldNames() { public Document toDocument(AggregationOperationContext context) { if (fields.size() == 1) { - return new Document(operator(), computeFieldName(fields.iterator().next(), context)); + return new Document(getOperator(), computeFieldName(fields.iterator().next(), context)); } - return new Document(operator(), + return new Document(getOperator(), fields.stream().map(it -> computeFieldName(it, context)).collect(Collectors.toList())); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$unset"; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java index 492afd2448..11e4dcaea5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java @@ -31,7 +31,8 @@ * @author Mark Paluch * @author Christoph Strobl * @since 1.3 - * @see MongoDB Aggregation Framework: $unwind + * @see MongoDB Aggregation Framework: + * $unwind */ public class UnwindOperation implements AggregationOperation, FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation { @@ -94,7 +95,7 @@ public Document toDocument(AggregationOperationContext context) { String path = context.getReference(field).toString(); if (!preserveNullAndEmptyArrays && arrayIndex == null) { - return new Document(operator(), path); + return new Document(getOperator(), path); } Document unwindArgs = new Document(); @@ -104,11 +105,15 @@ public Document toDocument(AggregationOperationContext context) { } unwindArgs.put("preserveNullAndEmptyArrays", preserveNullAndEmptyArrays); - return new Document(operator(), unwindArgs); + return new Document(getOperator(), unwindArgs); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ @Override - public String operator() { + public String getOperator() { return "$unwind"; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index 6be58d731d..abc994a050 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -99,17 +99,17 @@ public class AggregationTests { private static boolean initialized = false; @Template // - static MongoTestTemplate mongoTemplate; + private static MongoTestTemplate mongoTemplate; @BeforeEach - public void setUp() { + void setUp() { cleanDb(); initSampleDataIfNecessary(); } @AfterEach - public void cleanUp() { + void cleanUp() { cleanDb(); } @@ -167,25 +167,25 @@ public Void doInCollection(MongoCollection collection) throws MongoExc } @Test // DATAMONGO-586 - public void shouldHandleMissingInputCollection() { + void shouldHandleMissingInputCollection() { assertThatIllegalArgumentException() .isThrownBy(() -> mongoTemplate.aggregate(newAggregation(), (String) null, TagCount.class)); } @Test // DATAMONGO-586 - public void shouldHandleMissingAggregationPipeline() { + void shouldHandleMissingAggregationPipeline() { assertThatIllegalArgumentException() .isThrownBy(() -> mongoTemplate.aggregate(null, INPUT_COLLECTION, TagCount.class)); } @Test // DATAMONGO-586 - public void shouldHandleMissingEntityClass() { + void shouldHandleMissingEntityClass() { assertThatIllegalArgumentException() .isThrownBy(() -> mongoTemplate.aggregate(newAggregation(), INPUT_COLLECTION, null)); } @Test // DATAMONGO-586 - public void shouldAggregate() { + void shouldAggregate() { createTagDocuments(); @@ -214,7 +214,7 @@ public void shouldAggregate() { } @Test // DATAMONGO-1637 - public void shouldAggregateAndStream() { + void shouldAggregateAndStream() { createTagDocuments(); @@ -243,7 +243,7 @@ public void shouldAggregateAndStream() { } @Test // DATAMONGO-586 - public void shouldAggregateEmptyCollection() { + void shouldAggregateEmptyCollection() { Aggregation aggregation = newAggregation(// project("tags"), // @@ -266,7 +266,7 @@ public void shouldAggregateEmptyCollection() { } @Test // DATAMONGO-1637 - public void shouldAggregateEmptyCollectionAndStream() { + void shouldAggregateEmptyCollectionAndStream() { Aggregation aggregation = newAggregation(// project("tags"), // @@ -289,7 +289,7 @@ public void shouldAggregateEmptyCollectionAndStream() { } @Test // DATAMONGO-1391 - public void shouldUnwindWithIndex() { + void shouldUnwindWithIndex() { MongoCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); @@ -315,7 +315,7 @@ public void shouldUnwindWithIndex() { } @Test // DATAMONGO-1391 - public void shouldUnwindPreserveEmpty() { + void shouldUnwindPreserveEmpty() { MongoCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); @@ -341,7 +341,7 @@ public void shouldUnwindPreserveEmpty() { } @Test // DATAMONGO-586 - public void shouldDetectResultMismatch() { + void shouldDetectResultMismatch() { createTagDocuments(); @@ -366,7 +366,7 @@ public void shouldDetectResultMismatch() { } @Test // DATAMONGO-1637 - public void shouldDetectResultMismatchWhileStreaming() { + void shouldDetectResultMismatchWhileStreaming() { createTagDocuments(); @@ -391,7 +391,7 @@ public void shouldDetectResultMismatchWhileStreaming() { } @Test // DATAMONGO-586 - public void complexAggregationFrameworkUsageLargestAndSmallestCitiesByState() { + void complexAggregationFrameworkUsageLargestAndSmallestCitiesByState() { /* //complex mongodb aggregation framework example from https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state db.zipInfo.aggregate( @@ -499,11 +499,11 @@ public void complexAggregationFrameworkUsageLargestAndSmallestCitiesByState() { } @Test // DATAMONGO-586 - public void findStatesWithPopulationOver10MillionAggregationExample() { + void findStatesWithPopulationOver10MillionAggregationExample() { /* //complex mongodb aggregation framework example from https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state - + db.zipcodes.aggregate( { $group: { @@ -549,7 +549,7 @@ public void findStatesWithPopulationOver10MillionAggregationExample() { * Framework: $cond */ @Test // DATAMONGO-861 - public void aggregationUsingConditionalProjectionToCalculateDiscount() { + void aggregationUsingConditionalProjectionToCalculateDiscount() { /* db.inventory.aggregate( @@ -602,7 +602,7 @@ public void aggregationUsingConditionalProjectionToCalculateDiscount() { * Framework: $ifNull */ @Test // DATAMONGO-861 - public void aggregationUsingIfNullToProjectSaneDefaults() { + void aggregationUsingIfNullToProjectSaneDefaults() { /* db.inventory.aggregate( @@ -642,7 +642,7 @@ public void aggregationUsingIfNullToProjectSaneDefaults() { } @Test // DATAMONGO-861 - public void aggregationUsingConditionalProjection() { + void aggregationUsingConditionalProjection() { TypedAggregation aggregation = newAggregation(ZipInfo.class, // project() // @@ -664,7 +664,7 @@ public void aggregationUsingConditionalProjection() { } @Test // DATAMONGO-861 - public void aggregationUsingNestedConditionalProjection() { + void aggregationUsingNestedConditionalProjection() { TypedAggregation aggregation = newAggregation(ZipInfo.class, // project() // @@ -687,7 +687,7 @@ public void aggregationUsingNestedConditionalProjection() { } @Test // DATAMONGO-861 - public void aggregationUsingIfNullProjection() { + void aggregationUsingIfNullProjection() { mongoTemplate.insert(new LineItem("id", "caption", 0)); mongoTemplate.insert(new LineItem("idonly", null, 0)); @@ -711,7 +711,7 @@ public void aggregationUsingIfNullProjection() { } @Test // DATAMONGO-861 - public void aggregationUsingIfNullReplaceWithFieldReferenceProjection() { + void aggregationUsingIfNullReplaceWithFieldReferenceProjection() { mongoTemplate.insert(new LineItem("id", "caption", 0)); mongoTemplate.insert(new LineItem("idonly", null, 0)); @@ -735,7 +735,7 @@ public void aggregationUsingIfNullReplaceWithFieldReferenceProjection() { } @Test // DATAMONGO-861 - public void shouldAllowGroupingUsingConditionalExpressions() { + void shouldAllowGroupingUsingConditionalExpressions() { mongoTemplate.dropCollection(CarPerson.class); @@ -779,7 +779,7 @@ public void shouldAllowGroupingUsingConditionalExpressions() { } @Test // DATAMONGO-1784, DATAMONGO-2264 - public void shouldAllowSumUsingConditionalExpressions() { + void shouldAllowSumUsingConditionalExpressions() { mongoTemplate.dropCollection(CarPerson.class); @@ -827,7 +827,7 @@ public void shouldAllowSumUsingConditionalExpressions() { * the Five Most Common “Likes” */ @Test // DATAMONGO-586 - public void returnFiveMostCommonLikesAggregationFrameworkExample() { + void returnFiveMostCommonLikesAggregationFrameworkExample() { createUserWithLikesDocuments(); @@ -848,7 +848,7 @@ public void returnFiveMostCommonLikesAggregationFrameworkExample() { assertLikeStats(result.getMappedResults().get(4), "e", 3); } - protected TypedAggregation createUsersWithCommonLikesAggregation() { + TypedAggregation createUsersWithCommonLikesAggregation() { return newAggregation(UserWithLikes.class, // unwind("likes"), // group("likes").count().as("number"), // @@ -859,7 +859,7 @@ protected TypedAggregation createUsersWithCommonLikesAggregation( } @Test // DATAMONGO-586 - public void arithmenticOperatorsInProjectionExample() { + void arithmenticOperatorsInProjectionExample() { Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); mongoTemplate.insert(product); @@ -902,7 +902,7 @@ public void arithmenticOperatorsInProjectionExample() { } @Test // DATAMONGO-774 - public void expressionsInProjectionExample() { + void expressionsInProjectionExample() { Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); mongoTemplate.insert(product); @@ -934,7 +934,7 @@ public void expressionsInProjectionExample() { } @Test // DATAMONGO-774 - public void stringExpressionsInProjectionExample() { + void stringExpressionsInProjectionExample() { Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); mongoTemplate.insert(product); @@ -954,7 +954,7 @@ public void stringExpressionsInProjectionExample() { } @Test // DATAMONGO-774 - public void expressionsInProjectionExampleShowcase() { + void expressionsInProjectionExampleShowcase() { Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); mongoTemplate.insert(product); @@ -983,7 +983,7 @@ public void expressionsInProjectionExampleShowcase() { * Data MongoDB - Aggregation Framework - invalid reference in group Operation */ @Test // DATAMONGO-753 - public void allowsNestedFieldReferencesAsGroupIdsInGroupExpressions() { + void allowsNestedFieldReferencesAsGroupIdsInGroupExpressions() { mongoTemplate.insert(new DATAMONGO753().withPDs(new PD("A", 1), new PD("B", 1), new PD("C", 1))); mongoTemplate.insert(new DATAMONGO753().withPDs(new PD("B", 1), new PD("B", 1), new PD("C", 1))); @@ -1013,7 +1013,7 @@ public void allowsNestedFieldReferencesAsGroupIdsInGroupExpressions() { * Data MongoDB - Aggregation Framework - invalid reference in group Operation */ @Test // DATAMONGO-753 - public void aliasesNestedFieldInProjectionImmediately() { + void aliasesNestedFieldInProjectionImmediately() { mongoTemplate.insert(new DATAMONGO753().withPDs(new PD("A", 1), new PD("B", 1), new PD("C", 1))); mongoTemplate.insert(new DATAMONGO753().withPDs(new PD("B", 1), new PD("B", 1), new PD("C", 1))); @@ -1032,7 +1032,7 @@ public void aliasesNestedFieldInProjectionImmediately() { } @Test // DATAMONGO-774 - public void shouldPerformDateProjectionOperatorsCorrectly() throws ParseException { + void shouldPerformDateProjectionOperatorsCorrectly() throws ParseException { Data data = new Data(); data.stringValue = "ABC"; @@ -1058,7 +1058,7 @@ public void shouldPerformDateProjectionOperatorsCorrectly() throws ParseExceptio } @Test // DATAMONGO-774 - public void shouldPerformStringProjectionOperatorsCorrectly() throws ParseException { + void shouldPerformStringProjectionOperatorsCorrectly() throws ParseException { Data data = new Data(); data.dateValue = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss.SSSZ").parse("29.08.1983 12:34:56.789+0000"); @@ -1094,7 +1094,7 @@ public void shouldPerformStringProjectionOperatorsCorrectly() throws ParseExcept } @Test // DATAMONGO-1550 - public void shouldPerformReplaceRootOperatorCorrectly() throws ParseException { + void shouldPerformReplaceRootOperatorCorrectly() throws ParseException { Data data = new Data(); DataItem dataItem = new DataItem(); @@ -1115,7 +1115,7 @@ public void shouldPerformReplaceRootOperatorCorrectly() throws ParseException { } @Test // DATAMONGO-788, DATAMONGO-2264 - public void referencesToGroupIdsShouldBeRenderedProperly() { + void referencesToGroupIdsShouldBeRenderedProperly() { mongoTemplate.insert(new DATAMONGO788(1, 1)); mongoTemplate.insert(new DATAMONGO788(1, 1)); @@ -1142,7 +1142,7 @@ public void referencesToGroupIdsShouldBeRenderedProperly() { } @Test // DATAMONGO-806 - public void shouldAllowGroupByIdFields() { + void shouldAllowGroupByIdFields() { mongoTemplate.dropCollection(User.class); @@ -1173,7 +1173,7 @@ public void shouldAllowGroupByIdFields() { } @Test // DATAMONGO-840 - public void shouldAggregateOrderDataToAnInvoice() { + void shouldAggregateOrderDataToAnInvoice() { mongoTemplate.dropCollection(Order.class); @@ -1210,7 +1210,7 @@ public void shouldAggregateOrderDataToAnInvoice() { } @Test // DATAMONGO-924 - public void shouldAllowGroupingByAliasedFieldDefinedInFormerAggregationStage() { + void shouldAllowGroupingByAliasedFieldDefinedInFormerAggregationStage() { mongoTemplate.dropCollection(CarPerson.class); @@ -1241,7 +1241,7 @@ public void shouldAllowGroupingByAliasedFieldDefinedInFormerAggregationStage() { } @Test // DATAMONGO-960 - public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabled() { + void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabled() { createUserWithLikesDocuments(); @@ -1264,7 +1264,7 @@ public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOp } @Test // DATAMONGO-1637 - public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabledWhileStreaming() { + void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabledWhileStreaming() { createUserWithLikesDocuments(); @@ -1290,7 +1290,7 @@ public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOp } @Test // DATAMONGO-960 - public void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithExplainOptionEnabled() { + void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithExplainOptionEnabled() { createUserWithLikesDocuments(); @@ -1308,7 +1308,7 @@ public void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithEx } @Test // DATAMONGO-954, DATAMONGO-2264 - public void shouldSupportReturningCurrentAggregationRoot() { + void shouldSupportReturningCurrentAggregationRoot() { mongoTemplate.save(new Person("p1_first", "p1_last", 25)); mongoTemplate.save(new Person("p2_first", "p2_last", 32)); @@ -1333,7 +1333,7 @@ public void shouldSupportReturningCurrentAggregationRoot() { * {@link https://stackoverflow.com/questions/24185987/using-root-inside-spring-data-mongodb-for-retrieving-whole-document} */ @Test // DATAMONGO-954, DATAMONGO-2264 - public void shouldSupportReturningCurrentAggregationRootInReference() { + void shouldSupportReturningCurrentAggregationRootInReference() { mongoTemplate.save(new Reservation("0123", "42", 100)); mongoTemplate.save(new Reservation("0360", "43", 200)); @@ -1352,7 +1352,7 @@ public void shouldSupportReturningCurrentAggregationRootInReference() { } @Test // DATAMONGO-1549 - public void shouldApplyCountCorrectly() { + void shouldApplyCountCorrectly() { mongoTemplate.save(new Reservation("0123", "42", 100)); mongoTemplate.save(new Reservation("0360", "43", 200)); @@ -1371,7 +1371,7 @@ public void shouldApplyCountCorrectly() { } @Test // DATAMONGO-975 - public void shouldRetrieveDateTimeFragementsCorrectly() throws Exception { + void shouldRetrieveDateTimeFragementsCorrectly() throws Exception { mongoTemplate.dropCollection(ObjectWithDate.class); @@ -1424,7 +1424,7 @@ public void shouldRetrieveDateTimeFragementsCorrectly() throws Exception { } @Test // DATAMONGO-1127 - public void shouldSupportGeoNearQueriesForAggregationWithDistanceField() { + void shouldSupportGeoNearQueriesForAggregationWithDistanceField() { mongoTemplate.insertAll(Arrays.asList(TestEntities.geolocation().pennStation(), TestEntities.geolocation().tenGenOffice(), TestEntities.geolocation().flatironBuilding())); @@ -1444,7 +1444,7 @@ public void shouldSupportGeoNearQueriesForAggregationWithDistanceField() { } @Test // DATAMONGO-1348 - public void shouldSupportGeoJsonInGeoNearQueriesForAggregationWithDistanceField() { + void shouldSupportGeoJsonInGeoNearQueriesForAggregationWithDistanceField() { mongoTemplate.insert(new Venue("Penn Station", -73.99408, 40.75057)); mongoTemplate.insert(new Venue("10gen Office", -73.99171, 40.738868)); @@ -1466,7 +1466,7 @@ public void shouldSupportGeoJsonInGeoNearQueriesForAggregationWithDistanceField( } @Test // DATAMONGO-1348 - public void shouldSupportGeoJsonInGeoNearQueriesForAggregationWithDistanceFieldInMiles() { + void shouldSupportGeoJsonInGeoNearQueriesForAggregationWithDistanceFieldInMiles() { mongoTemplate.insert(new Venue("Penn Station", -73.99408, 40.75057)); mongoTemplate.insert(new Venue("10gen Office", -73.99171, 40.738868)); @@ -1489,7 +1489,7 @@ public void shouldSupportGeoJsonInGeoNearQueriesForAggregationWithDistanceFieldI } @Test // DATAMONGO-1133 - public void shouldHonorFieldAliasesForFieldReferences() { + void shouldHonorFieldAliasesForFieldReferences() { mongoTemplate.insert(new MeterData("m1", "counter1", 42)); mongoTemplate.insert(new MeterData("m1", "counter1", 13)); @@ -1509,7 +1509,7 @@ public void shouldHonorFieldAliasesForFieldReferences() { } @Test // DATAMONGO-1326 - public void shouldLookupPeopleCorectly() { + void shouldLookupPeopleCorectly() { createUsersWithReferencedPersons(); @@ -1528,7 +1528,7 @@ public void shouldLookupPeopleCorectly() { } @Test // DATAMONGO-1326 - public void shouldGroupByAndLookupPeopleCorectly() { + void shouldGroupByAndLookupPeopleCorectly() { createUsersWithReferencedPersons(); @@ -1549,7 +1549,7 @@ public void shouldGroupByAndLookupPeopleCorectly() { @Test // DATAMONGO-1418, DATAMONGO-1824 @MongoVersion(asOf = "2.6") - public void shouldCreateOutputCollection() { + void shouldCreateOutputCollection() { createPersonDocuments(); @@ -1573,7 +1573,7 @@ public void shouldCreateOutputCollection() { } @Test // DATAMONGO-1637 - public void shouldCreateOutputCollectionWhileStreaming() { + void shouldCreateOutputCollectionWhileStreaming() { createPersonDocuments(); @@ -1595,7 +1595,7 @@ public void shouldCreateOutputCollectionWhileStreaming() { } @Test // DATAMONGO-1637 - public void shouldReturnDocumentsWithOutputCollectionWhileStreaming() { + void shouldReturnDocumentsWithOutputCollectionWhileStreaming() { createPersonDocuments(); @@ -1626,7 +1626,7 @@ private void createPersonDocuments() { } @Test // DATAMONGO-1418, DATAMONGO-2536 - public void outShouldOutBeTheLastOperation() { + void outShouldOutBeTheLastOperation() { assertThatIllegalArgumentException().isThrownBy(() -> newAggregation(match(new Criteria()), // group("field1").count().as("totalCount"), // out("collection1"), // @@ -1634,7 +1634,7 @@ public void outShouldOutBeTheLastOperation() { } @Test // DATAMONGO-1325 - public void shouldApplySampleCorrectly() { + void shouldApplySampleCorrectly() { createUserWithLikesDocuments(); @@ -1651,7 +1651,7 @@ public void shouldApplySampleCorrectly() { @Test // DATAMONGO-1457 @MongoVersion(asOf = "3.2") - public void sliceShouldBeAppliedCorrectly() { + void sliceShouldBeAppliedCorrectly() { createUserWithLikesDocuments(); @@ -1667,7 +1667,7 @@ public void sliceShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1491 - public void filterShouldBeAppliedCorrectly() { + void filterShouldBeAppliedCorrectly() { Item item43 = Item.builder().itemId("43").quantity(2).price(2L).build(); Item item2 = Item.builder().itemId("2").quantity(1).price(240L).build(); @@ -1697,7 +1697,7 @@ public void filterShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1538 - public void letShouldBeAppliedCorrectly() { + void letShouldBeAppliedCorrectly() { Sales2 sales1 = Sales2.builder().id("1").price(10).tax(0.5F).applyDiscount(true).build(); Sales2 sales2 = Sales2.builder().id("2").price(10).tax(0.25F).applyDiscount(false).build(); @@ -1721,7 +1721,7 @@ public void letShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1551, DATAMONGO-2264 - public void graphLookupShouldBeAppliedCorrectly() { + void graphLookupShouldBeAppliedCorrectly() { Employee em1 = Employee.builder().id(1).name("Dev").build(); Employee em2 = Employee.builder().id(2).name("Eliot").reportsTo("Dev").build(); @@ -1753,7 +1753,7 @@ public void graphLookupShouldBeAppliedCorrectly() { } @Test // DATAMONGO-1552 - public void bucketShouldCollectDocumentsIntoABucket() { + void bucketShouldCollectDocumentsIntoABucket() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); Art a2 = Art.builder().id(2).title("Melancholy III").artist("Munch").year(1902).price(280.00).build(); @@ -1787,7 +1787,7 @@ public void bucketShouldCollectDocumentsIntoABucket() { } @Test // DATAMONGO-1552, DATAMONGO-2437 - public void bucketAutoShouldCollectDocumentsIntoABucket() { + void bucketAutoShouldCollectDocumentsIntoABucket() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); Art a2 = Art.builder().id(2).title("Melancholy III").artist("Munch").year(1902).price(280.00).build(); @@ -1820,7 +1820,7 @@ public void bucketAutoShouldCollectDocumentsIntoABucket() { } @Test // DATAMONGO-1552 - public void facetShouldCreateFacets() { + void facetShouldCreateFacets() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); Art a2 = Art.builder().id(2).title("Melancholy III").artist("Munch").year(1902).price(280.00).build(); @@ -1863,7 +1863,7 @@ public void facetShouldCreateFacets() { } @Test // DATAMONGO-1986 - public void runMatchOperationCriteriaThroughQueryMapperForTypedAggregation() { + void runMatchOperationCriteriaThroughQueryMapperForTypedAggregation() { mongoTemplate.insertAll(TestEntities.geolocation().newYork()); @@ -1878,7 +1878,7 @@ public void runMatchOperationCriteriaThroughQueryMapperForTypedAggregation() { } @Test // DATAMONGO-1986 - public void runMatchOperationCriteriaThroughQueryMapperForUntypedAggregation() { + void runMatchOperationCriteriaThroughQueryMapperForUntypedAggregation() { mongoTemplate.insertAll(TestEntities.geolocation().newYork()); @@ -1893,7 +1893,7 @@ public void runMatchOperationCriteriaThroughQueryMapperForUntypedAggregation() { } @Test // DATAMONGO-2437 - public void shouldReadComplexIdValueCorrectly() { + void shouldReadComplexIdValueCorrectly() { WithComplexId source = new WithComplexId(); source.id = new ComplexId(); @@ -1908,7 +1908,7 @@ public void shouldReadComplexIdValueCorrectly() { } @Test // DATAMONGO-2536 - public void skipOutputDoesNotReadBackAggregationResults() { + void skipOutputDoesNotReadBackAggregationResults() { createTagDocuments(); @@ -2021,7 +2021,7 @@ static class PD { String pDch; @org.springframework.data.mongodb.core.mapping.Field("alias") int up; - public PD(String pDch, int up) { + PD(String pDch, int up) { this.pDch = pDch; this.up = up; } @@ -2036,7 +2036,7 @@ static class DATAMONGO788 { public DATAMONGO788() {} - public DATAMONGO788(int x, int y) { + DATAMONGO788(int x, int y) { this.x = x; this.xField = x; this.y = y; @@ -2052,7 +2052,7 @@ static class User { public User() {} - public User(String id, PushMessage... msgs) { + User(String id, PushMessage... msgs) { this.id = id; this.msgs = Arrays.asList(msgs); } @@ -2067,7 +2067,7 @@ static class PushMessage { public PushMessage() {} - public PushMessage(String id, String content, Date createDate) { + PushMessage(String id, String content, Date createDate) { this.id = id; this.content = content; this.createDate = createDate; @@ -2082,7 +2082,7 @@ static class CarPerson { private String lastName; private Descriptors descriptors; - public CarPerson(String firstname, String lastname, Entry... entries) { + CarPerson(String firstname, String lastname, Entry... entries) { this.firstName = firstname; this.lastName = lastname; @@ -2102,7 +2102,7 @@ static class CarDescriptor { private List entries = new ArrayList(); - public CarDescriptor(Entry... entries) { + CarDescriptor(Entry... entries) { for (Entry entry : entries) { this.entries.add(entry); @@ -2118,7 +2118,7 @@ static class Entry { public Entry() {} - public Entry(String make, String model, int year) { + Entry(String make, String model, int year) { this.make = make; this.model = model; this.year = year; @@ -2134,7 +2134,7 @@ static class Reservation { public Reservation() {} - public Reservation(String hotelCode, String confirmationNumber, int timestamp) { + Reservation(String hotelCode, String confirmationNumber, int timestamp) { this.hotelCode = hotelCode; this.confirmationNumber = confirmationNumber; this.timestamp = timestamp; @@ -2145,7 +2145,7 @@ static class ObjectWithDate { Date dateValue; - public ObjectWithDate(Date dateValue) { + ObjectWithDate(Date dateValue) { this.dateValue = dateValue; } } @@ -2161,14 +2161,14 @@ static class InventoryItem { public InventoryItem() {} - public InventoryItem(int id, String item, int qty) { + InventoryItem(int id, String item, int qty) { this.id = id; this.item = item; this.qty = qty; } - public InventoryItem(int id, String item, String description, int qty) { + InventoryItem(int id, String item, String description, int qty) { this.id = id; this.item = item; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java index 61d3834b40..9051c27b21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReactiveAggregationTests.java @@ -181,5 +181,4 @@ public void skipOutputDoesNotReadBackAggregationResults() { reactiveMongoTemplate.aggregate(agg, Document.class).as(StepVerifier::create).verifyComplete(); } - } From 6bafcea5394297d1c92c5b5c9671cc46adcba3ee Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 14 Jul 2020 11:23:31 +0200 Subject: [PATCH 0218/1381] DATAMONGO-2586 - Add support for reactive auditing. We now provide a fully reactive variant for auditing with EnableReactiveMongoAuditing. Original Pull Request: #877 --- .../mongodb/config/EnableMongoAuditing.java | 4 +- .../config/EnableReactiveMongoAuditing.java | 70 +++++++++++++ .../config/MongoAuditingRegistrar.java | 74 +------------- .../config/PersistentEntitiesFactoryBean.java | 68 +++++++++++++ .../ReactiveMongoAuditingRegistrar.java | 97 +++++++++++++++++++ .../event/ReactiveAuditingEntityCallback.java | 13 ++- .../mongodb/config/ReactiveAuditingTests.java | 36 +++---- .../ReactiveMongoTemplateAuditingTests.java | 19 ++-- src/main/asciidoc/new-features.adoc | 5 + .../asciidoc/reference/mongo-auditing.adoc | 19 ++++ 10 files changed, 300 insertions(+), 105 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java index 98bd186da2..e934dc2114 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java @@ -61,8 +61,8 @@ boolean modifyOnCreate() default true; /** - * Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be - * used for setting creation and modification dates. + * Configures a {@link DateTimeProvider} bean name that allows customizing the timestamp to be used for setting + * creation and modification dates. * * @return empty {@link String} by default. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java new file mode 100644 index 0000000000..d7e6b2033e --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java @@ -0,0 +1,70 @@ +/* + * Copyright 2020 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 + * + * https://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.config; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; +import org.springframework.data.auditing.DateTimeProvider; +import org.springframework.data.domain.ReactiveAuditorAware; + +/** + * Annotation to enable auditing in MongoDB using reactive infrastructure via annotation configuration. + * + * @author Mark Paluch + * @since 3.1 + */ +@Inherited +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(ReactiveMongoAuditingRegistrar.class) +public @interface EnableReactiveMongoAuditing { + + /** + * Configures the {@link ReactiveAuditorAware} bean to be used to lookup the current principal. + * + * @return empty {@link String} by default. + */ + String auditorAwareRef() default ""; + + /** + * Configures whether the creation and modification dates are set. Defaults to {@literal true}. + * + * @return {@literal true} by default. + */ + boolean setDates() default true; + + /** + * Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}. + * + * @return {@literal true} by default. + */ + boolean modifyOnCreate() default true; + + /** + * Configures a {@link DateTimeProvider} bean name that allows customizing the timestamp to be used for setting + * creation and modification dates. + * + * @return empty {@link String} by default. + */ + String dateTimeProviderRef() default ""; +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java index f842b9b738..eb6366d2a6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java @@ -17,7 +17,6 @@ import java.lang.annotation.Annotation; -import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -28,14 +27,8 @@ import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; import org.springframework.data.auditing.config.AuditingConfiguration; import org.springframework.data.config.ParsingUtils; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; -import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback; -import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; /** * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableMongoAuditing} annotation. @@ -46,9 +39,6 @@ */ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport { - private static boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono", - MongoAuditingRegistrar.class.getClassLoader()); - /* * (non-Javadoc) * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation() @@ -91,7 +81,7 @@ protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingCon BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(IsNewAwareAuditingHandler.class); - BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(MongoMappingContextLookup.class); + BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntitiesFactoryBean.class); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); builder.addConstructorArgValue(definition.getBeanDefinition()); @@ -116,68 +106,6 @@ protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandle registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(), AuditingEntityCallback.class.getName(), registry); - - if (PROJECT_REACTOR_AVAILABLE) { - registerReactiveAuditingEntityCallback(registry, auditingHandlerDefinition.getSource()); - } } - private void registerReactiveAuditingEntityCallback(BeanDefinitionRegistry registry, Object source) { - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class); - - builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry)); - builder.getRawBeanDefinition().setSource(source); - - registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(), - registry); - } - - /** - * Simple helper to be able to wire the {@link MappingContext} from a {@link MappingMongoConverter} bean available in - * the application context. - * - * @author Oliver Gierke - */ - static class MongoMappingContextLookup - implements FactoryBean, MongoPersistentProperty>> { - - private final MappingMongoConverter converter; - - /** - * Creates a new {@link MongoMappingContextLookup} for the given {@link MappingMongoConverter}. - * - * @param converter must not be {@literal null}. - */ - public MongoMappingContextLookup(MappingMongoConverter converter) { - this.converter = converter; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObject() - */ - @Override - public MappingContext, MongoPersistentProperty> getObject() throws Exception { - return converter.getMappingContext(); - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObjectType() - */ - @Override - public Class getObjectType() { - return MappingContext.class; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#isSingleton() - */ - @Override - public boolean isSingleton() { - return true; - } - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java new file mode 100644 index 0000000000..474559228d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013-2020 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 + * + * https://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.config; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; + +/** + * Simple helper to be able to wire the {@link PersistentEntities} from a {@link MappingMongoConverter} bean available + * in the application context. + * + * @author Oliver Gierke + * @author Mark Paluch + */ +class PersistentEntitiesFactoryBean implements FactoryBean { + + private final MappingMongoConverter converter; + + /** + * Creates a new {@link PersistentEntitiesFactoryBean} for the given {@link MappingMongoConverter}. + * + * @param converter must not be {@literal null}. + */ + public PersistentEntitiesFactoryBean(MappingMongoConverter converter) { + this.converter = converter; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObject() + */ + @Override + public PersistentEntities getObject() throws Exception { + return PersistentEntities.of(converter.getMappingContext()); + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ + @Override + public Class getObjectType() { + return PersistentEntities.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#isSingleton() + */ + @Override + public boolean isSingleton() { + return true; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java new file mode 100644 index 0000000000..20f7d16602 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java @@ -0,0 +1,97 @@ +/* + * Copyright 2020 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 + * + * https://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.config; + +import java.lang.annotation.Annotation; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler; +import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; +import org.springframework.data.auditing.config.AuditingConfiguration; +import org.springframework.data.config.ParsingUtils; +import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback; +import org.springframework.util.Assert; + +/** + * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableReactiveMongoAuditing} annotation. + * + * @author Mark Paluch + * @since 3.1 + */ +class ReactiveMongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport { + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation() + */ + @Override + protected Class getAnnotation() { + return EnableReactiveMongoAuditing.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditingHandlerBeanName() + */ + @Override + protected String getAuditingHandlerBeanName() { + return "reactiveMongoAuditingHandler"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditHandlerBeanDefinitionBuilder(org.springframework.data.auditing.config.AuditingConfiguration) + */ + @Override + protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingConfiguration configuration) { + + Assert.notNull(configuration, "AuditingConfiguration must not be null!"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveIsNewAwareAuditingHandler.class); + + BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntitiesFactoryBean.class); + definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); + + builder.addConstructorArgValue(definition.getBeanDefinition()); + return configureDefaultAuditHandlerAttributes(configuration, builder); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerAuditListener(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry) + */ + @Override + protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition, + BeanDefinitionRegistry registry) { + + Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null!"); + Assert.notNull(registry, "BeanDefinitionRegistry must not be null!"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class); + + builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry)); + builder.getRawBeanDefinition().setSource(auditingHandlerDefinition.getSource()); + + registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(), + registry); + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java index 368257067d..4c1e9146fa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java @@ -15,13 +15,12 @@ */ package org.springframework.data.mongodb.core.mapping.event; -import reactor.core.publisher.Mono; - import org.reactivestreams.Publisher; + import org.springframework.beans.factory.ObjectFactory; import org.springframework.core.Ordered; import org.springframework.data.auditing.AuditingHandler; -import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler; import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.context.MappingContext; import org.springframework.util.Assert; @@ -34,7 +33,7 @@ */ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCallback, Ordered { - private final ObjectFactory auditingHandlerFactory; + private final ObjectFactory auditingHandlerFactory; /** * Creates a new {@link ReactiveAuditingEntityCallback} using the given {@link MappingContext} and @@ -42,19 +41,19 @@ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCall * * @param auditingHandlerFactory must not be {@literal null}. */ - public ReactiveAuditingEntityCallback(ObjectFactory auditingHandlerFactory) { + public ReactiveAuditingEntityCallback(ObjectFactory auditingHandlerFactory) { Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!"); this.auditingHandlerFactory = auditingHandlerFactory; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeConvertCallback#onBeforeConvert(java.lang.Object, java.lang.String) */ @Override public Publisher onBeforeConvert(Object entity, String collection) { - return Mono.just(auditingHandlerFactory.getObject().markAudited(entity)); + return auditingHandlerFactory.getObject().markAudited(entity); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index f79b88e456..7f2ce737e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.config; import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -30,13 +29,14 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Version; -import org.springframework.data.domain.AuditorAware; +import org.springframework.data.domain.ReactiveAuditorAware; import org.springframework.data.mongodb.core.AuditablePerson; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -57,17 +57,16 @@ */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration -public class ReactiveAuditingTests { +class ReactiveAuditingTests { static @Client MongoClient mongoClient; @Autowired ReactiveAuditablePersonRepository auditablePersonRepository; - @Autowired AuditorAware auditorAware; @Autowired MongoMappingContext context; @Autowired ReactiveMongoOperations operations; @Configuration - @EnableMongoAuditing(auditorAwareRef = "auditorProvider") + @EnableReactiveMongoAuditing @EnableReactiveMongoRepositories(basePackageClasses = ReactiveAuditingTests.class, considerNestedRepositories = true, includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ReactiveAuditablePersonRepository.class)) static class Config extends AbstractReactiveMongoConfiguration { @@ -89,14 +88,17 @@ protected Set> getInitialEntitySet() { } @Bean - @SuppressWarnings("unchecked") - public AuditorAware auditorProvider() { - return mock(AuditorAware.class); + public ReactiveAuditorAware auditorProvider() { + + AuditablePerson person = new AuditablePerson("some-person"); + person.setId("foo"); + + return () -> Mono.just(person); } } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithWrapperVersion() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithWrapperVersion() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -106,7 +108,7 @@ public void auditingWorksForVersionedEntityWithWrapperVersion() { } @Test // DATAMONGO-2179 - public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { + void auditingWorksForVersionedEntityBatchWithWrapperVersion() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -115,8 +117,8 @@ public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { null, 0L, 1L); } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithSimpleVersion() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithSimpleVersion() { verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // it -> it.version, // @@ -125,8 +127,8 @@ public void auditingWorksForVersionedEntityWithSimpleVersion() { 0L, 1L, 2L); } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -135,8 +137,8 @@ public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { null, 0L, 1L); } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // it -> it.version, // AuditablePerson::getCreatedAt, // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 46b575f35f..78b1f05f2f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.*; +import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import reactor.util.function.Tuples; @@ -29,14 +30,17 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.Version; +import org.springframework.data.domain.ReactiveAuditorAware; import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; -import org.springframework.data.mongodb.config.EnableMongoAuditing; +import org.springframework.data.mongodb.config.EnableReactiveMongoAuditing; import org.springframework.data.mongodb.core.KAuditableVersionedEntity; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.mapping.Document; @@ -50,17 +54,20 @@ import com.mongodb.reactivestreams.client.MongoClient; /** + * Integration tests for {@link EnableReactiveMongoAuditing} through {@link ReactiveMongoTemplate}. + * * @author Christoph Strobl + * @author Mark Paluch */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) -public class ReactiveMongoTemplateAuditingTests { +class ReactiveMongoTemplateAuditingTests { static final String DB_NAME = "mongo-template-audit-tests"; static @Client MongoClient mongoClient; @Configuration - @EnableMongoAuditing + @EnableReactiveMongoAuditing static class Conf extends AbstractReactiveMongoConfiguration { @Bean @@ -84,7 +91,7 @@ protected Set> getInitialEntitySet() { @Autowired MongoClient client; @BeforeEach - public void setUp() { + void setUp() { MongoTestUtils.flushCollection(DB_NAME, template.getCollectionName(ImmutableAuditableEntityWithVersion.class), client); @@ -92,7 +99,7 @@ public void setUp() { } @Test // DATAMONGO-2346 - public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSave() { + void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSave() { ImmutableAuditableEntityWithVersion entity = new ImmutableAuditableEntityWithVersion(null, "value", null, null); @@ -114,7 +121,7 @@ public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSa } @Test // DATAMONGO-2346 - public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEntityOnSave() { + void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEntityOnSave() { KAuditableVersionedEntity entity = new KAuditableVersionedEntity(null, "value", null, null); diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 1a1fc849d9..d0c9317f81 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,6 +1,11 @@ [[new-features]] = New & Noteworthy +[[new-features.3.1]] +== What's New in Spring Data MongoDB 3.1 + +* <> enabled through `@EnableReactiveMongoAuditing`. `@EnableMongoAuditing` no longer registers `ReactiveAuditingEntityCallback`. + [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 diff --git a/src/main/asciidoc/reference/mongo-auditing.adoc b/src/main/asciidoc/reference/mongo-auditing.adoc index eabc532c0c..b7abbe7112 100644 --- a/src/main/asciidoc/reference/mongo-auditing.adoc +++ b/src/main/asciidoc/reference/mongo-auditing.adoc @@ -30,3 +30,22 @@ To activate auditing functionality via XML, add the Spring Data Mongo `auditing` ---- ==== +If you wish to use auditing with the reactive programming model, then enable auditing through `@EnableReactiveMongoAuditing` + +.Activating auditing using JavaConfig +==== +[source,java] +---- +@Configuration +@EnableReactiveMongoAuditing +class Config { + + @Bean + public ReactiveAuditorAware myAuditorProvider() { + return new AuditorAwareImpl(); + } +} +---- +==== +If you expose a bean of type `ReactiveAuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableReactiveMongoAuditing`. + From a8a364c2deaede9f096a2a6220f1f6eb8efb9869 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 17 Jul 2020 10:40:07 +0200 Subject: [PATCH 0219/1381] DATAMONGO-2586 - Polishing. Add tests to ensure no reactive auditing callback is registered when using imperative configuration and vice versa. Update wording and minor code style tweaks. Original Pull Request: #877 --- .../config/PersistentEntitiesFactoryBean.java | 15 ++----- ...uditingViaJavaConfigRepositoriesTests.java | 40 ++++++++++++++----- .../mongodb/config/ReactiveAuditingTests.java | 19 +++++++++ .../asciidoc/reference/mongo-auditing.adoc | 7 ++-- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java index 474559228d..b2045db43b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2020 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. @@ -25,6 +25,8 @@ * * @author Oliver Gierke * @author Mark Paluch + * @author Christoph Strobl + * @since 3.1 */ class PersistentEntitiesFactoryBean implements FactoryBean { @@ -44,7 +46,7 @@ public PersistentEntitiesFactoryBean(MappingMongoConverter converter) { * @see org.springframework.beans.factory.FactoryBean#getObject() */ @Override - public PersistentEntities getObject() throws Exception { + public PersistentEntities getObject() { return PersistentEntities.of(converter.getMappingContext()); } @@ -56,13 +58,4 @@ public PersistentEntities getObject() throws Exception { public Class getObjectType() { return PersistentEntities.class; } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#isSingleton() - */ - @Override - public boolean isSingleton() { - return true; - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java index 27e3b05b71..24b9e94140 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Function; @@ -34,12 +35,16 @@ import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; +import org.springframework.core.ResolvableType; import org.springframework.data.annotation.Version; import org.springframework.data.domain.AuditorAware; +import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mongodb.core.AuditablePerson; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback; +import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.test.util.Client; @@ -48,6 +53,7 @@ import org.springframework.stereotype.Repository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.client.MongoClient; @@ -60,7 +66,7 @@ */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration -public class AuditingViaJavaConfigRepositoriesTests { +class AuditingViaJavaConfigRepositoriesTests { static @Client MongoClient mongoClient; @@ -79,6 +85,7 @@ static class Config extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { + return "database"; } @@ -101,13 +108,13 @@ protected Set> getInitialEntitySet() throws ClassNotFoundException { } @BeforeEach - public void setup() { + void setup() { auditablePersonRepository.deleteAll(); this.auditor = auditablePersonRepository.save(new AuditablePerson("auditor")); } @Test // DATAMONGO-792, DATAMONGO-883 - public void basicAuditing() { + void basicAuditing() { doReturn(Optional.of(this.auditor)).when(this.auditorAware).getCurrentAuditor(); @@ -122,18 +129,18 @@ public void basicAuditing() { @Test // DATAMONGO-843 @SuppressWarnings("resource") - public void auditingUsesFallbackMappingContextIfNoneConfiguredWithRepositories() { + void auditingUsesFallbackMappingContextIfNoneConfiguredWithRepositories() { new AnnotationConfigApplicationContext(SimpleConfigWithRepositories.class); } @Test // DATAMONGO-843 @SuppressWarnings("resource") - public void auditingUsesFallbackMappingContextIfNoneConfigured() { + void auditingUsesFallbackMappingContextIfNoneConfigured() { new AnnotationConfigApplicationContext(SimpleConfig.class); } @Test // DATAMONGO-2139 - public void auditingWorksForVersionedEntityWithWrapperVersion() { + void auditingWorksForVersionedEntityWithWrapperVersion() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -143,7 +150,7 @@ public void auditingWorksForVersionedEntityWithWrapperVersion() { } @Test // DATAMONGO-2179 - public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { + void auditingWorksForVersionedEntityBatchWithWrapperVersion() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -153,7 +160,7 @@ public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { } @Test // DATAMONGO-2139 - public void auditingWorksForVersionedEntityWithSimpleVersion() { + void auditingWorksForVersionedEntityWithSimpleVersion() { verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // it -> it.version, // @@ -163,7 +170,7 @@ public void auditingWorksForVersionedEntityWithSimpleVersion() { } @Test // DATAMONGO-2139 - public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { + void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -173,7 +180,7 @@ public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { } @Test // DATAMONGO-2139 - public void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { + void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // it -> it.version, // @@ -182,6 +189,19 @@ public void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { 0L, 1L, 2L); } + @Test // DATAMONGO-2586 + void auditingShouldOnlyRegisterImperativeAuditingCallback() { + + Object callbacks = ReflectionTestUtils.getField(operations, "entityCallbacks"); + Object callbackDiscoverer = ReflectionTestUtils.getField(callbacks, "callbackDiscoverer"); + List> actualCallbacks = ReflectionTestUtils.invokeMethod(callbackDiscoverer, "getEntityCallbacks", + AuditablePerson.class, ResolvableType.forClass(EntityCallback.class)); + + assertThat(actualCallbacks) // + .hasAtLeastOneElementOfType(AuditingEntityCallback.class) // + .doesNotHaveAnyElementsOfTypes(ReactiveAuditingEntityCallback.class); + } + private void verifyAuditingViaVersionProperty(T instance, Function versionExtractor, Function createdDateExtractor, Function persister, Object... expectedValues) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index 7f2ce737e7..c4c157d185 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -17,12 +17,18 @@ import static org.assertj.core.api.Assertions.*; +import org.springframework.core.ResolvableType; +import org.springframework.data.mapping.callback.EntityCallback; +import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback; +import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback; +import org.springframework.test.util.ReflectionTestUtils; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -146,6 +152,19 @@ void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { 0L, 1L, 2L); } + @Test // DATAMONGO-2586 + void auditingShouldOnlyRegisterReactiveAuditingCallback() { + + Object callbacks = ReflectionTestUtils.getField(operations, "entityCallbacks"); + Object callbackDiscoverer = ReflectionTestUtils.getField(callbacks, "callbackDiscoverer"); + List> actualCallbacks = ReflectionTestUtils.invokeMethod(callbackDiscoverer, "getEntityCallbacks", + AuditablePerson.class, ResolvableType.forClass(EntityCallback.class)); + + assertThat(actualCallbacks) // + .hasAtLeastOneElementOfType(ReactiveAuditingEntityCallback.class) // + .doesNotHaveAnyElementsOfTypes(AuditingEntityCallback.class); + } + private void verifyAuditingViaVersionProperty(T instance, Function versionExtractor, Function createdDateExtractor, Function> persister, Object... expectedValues) { diff --git a/src/main/asciidoc/reference/mongo-auditing.adoc b/src/main/asciidoc/reference/mongo-auditing.adoc index b7abbe7112..2b1ae38314 100644 --- a/src/main/asciidoc/reference/mongo-auditing.adoc +++ b/src/main/asciidoc/reference/mongo-auditing.adoc @@ -30,9 +30,10 @@ To activate auditing functionality via XML, add the Spring Data Mongo `auditing` ---- ==== -If you wish to use auditing with the reactive programming model, then enable auditing through `@EnableReactiveMongoAuditing` +To enable auditing, leveraging a reactive programming model, use the `@EnableReactiveMongoAuditing` annotation. + +If you expose a bean of type `ReactiveAuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableReactiveMongoAuditing`. -.Activating auditing using JavaConfig +.Activating reactive auditing using JavaConfig ==== [source,java] ---- @@ -47,5 +48,5 @@ class Config { } ---- ==== -If you expose a bean of type `ReactiveAuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableReactiveMongoAuditing`. + From 1b5a22730b47fdd98bf7c44c4863ba5ed3c77278 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 Jul 2020 09:31:02 +0200 Subject: [PATCH 0220/1381] DATAMONGO-2566 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 6ce67e24ee..5a52ed47d9 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.19.RELEASE (2020-07-22) +---------------------------------------------- +* DATAMONGO-2572 - Remove usage of Oppressive Language. +* DATAMONGO-2570 - Avoiding unintentional unboxing. +* DATAMONGO-2566 - Release 2.1.19 (Lovelace SR19). + + Changes in version 3.1.0-M1 (2020-06-25) ---------------------------------------- * DATAMONGO-2576 - Upgrade to Hibernate Validator 5.4.3. @@ -3083,4 +3090,5 @@ Repository + From 79c647a4d8a4d0774b5e3fe67900861aada77279 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 Jul 2020 09:55:18 +0200 Subject: [PATCH 0221/1381] DATAMONGO-2567 - Updated changelog. --- src/main/resources/changelog.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 5a52ed47d9..63a8a66522 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,15 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.9.RELEASE (2020-07-22) +--------------------------------------------- +* DATAMONGO-2572 - Remove usage of Oppressive Language. +* DATAMONGO-2571 - regex expression included "/" character can't be parsed in the stage of aggregation annotation. +* DATAMONGO-2570 - Avoiding unintentional unboxing. +* DATAMONGO-2567 - Release 2.2.9 (Moore SR9). +* DATAMONGO-2490 - @DBRef fetched without ClientSession when using Spring Transactions. + + Changes in version 2.1.19.RELEASE (2020-07-22) ---------------------------------------------- * DATAMONGO-2572 - Remove usage of Oppressive Language. @@ -3090,5 +3099,6 @@ Repository + From 430c166a2b13e09abb6aa9622311b62930d076fe Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 Jul 2020 10:20:31 +0200 Subject: [PATCH 0222/1381] DATAMONGO-2568 - Updated changelog. --- src/main/resources/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 63a8a66522..4d660632dd 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,17 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.2.RELEASE (2020-07-22) +--------------------------------------------- +* DATAMONGO-2589 - Upgrade to MongoDB Driver 4.0.5. +* DATAMONGO-2572 - Remove usage of Oppressive Language. +* DATAMONGO-2571 - regex expression included "/" character can't be parsed in the stage of aggregation annotation. +* DATAMONGO-2570 - Avoiding unintentional unboxing. +* DATAMONGO-2568 - Release 3.0.2 (Neumann SR2). +* DATAMONGO-2536 - Add option to discard results on $out and $merge. +* DATAMONGO-2490 - @DBRef fetched without ClientSession when using Spring Transactions. + + Changes in version 2.2.9.RELEASE (2020-07-22) --------------------------------------------- * DATAMONGO-2572 - Remove usage of Oppressive Language. @@ -3100,5 +3111,6 @@ Repository + From 00aaf2145bb22d7f5d3aadbf6e7401056520d0a8 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 17 Jul 2020 15:04:40 +0200 Subject: [PATCH 0223/1381] DATAMONGO-2591 - Upgrade MongoDB drivers to 4.1.0-rc0. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f50a5f840f..98fb76d5c0 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.4.0-SNAPSHOT - 4.0.4 + 4.1.0-rc0 ${mongo} 1.19 From 66fae82798acd4d989394ffd92c6a991b3a6a9cb Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 30 Jun 2020 12:12:44 +0200 Subject: [PATCH 0224/1381] DATAMONGO-1894 - Use reactive SpEL extensions for SpEL evaluation in query execution. Original Pull Request: #874 --- .../query/AbstractReactiveMongoQuery.java | 55 +++++---- .../repository/query/CollationUtils.java | 5 +- .../query/DefaultSpELExpressionEvaluator.java | 47 ++++++++ .../query/NoOpExpressionEvaluator.java | 34 ++++++ .../query/ReactiveMongoQueryExecution.java | 10 +- .../query/ReactivePartTreeMongoQuery.java | 16 +-- .../query/ReactiveStringBasedAggregation.java | 105 ++++++++++++------ .../query/ReactiveStringBasedMongoQuery.java | 57 +++++++--- .../query/StringBasedMongoQuery.java | 29 ++++- .../ReactiveMongoRepositoryFactory.java | 8 +- .../ReactiveMongoRepositoryFactoryBean.java | 24 ++-- .../util/json/ParameterBindingContext.java | 66 +++++++---- .../json/ParameterBindingDocumentCodec.java | 53 ++++++++- .../util/json/ParameterBindingJsonReader.java | 1 + .../ReactiveMongoRepositoryTests.java | 3 +- .../SimpleReactiveMongoRepositoryTests.java | 3 +- .../AbstractReactiveMongoQueryUnitTests.java | 41 ++++--- ...activeStringBasedAggregationUnitTests.java | 6 +- ...eactiveStringBasedMongoQueryUnitTests.java | 84 ++++++++++++-- .../ParameterBindingJsonReaderUnitTests.java | 26 +++++ 20 files changed, 517 insertions(+), 156 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index 69c834e4fa..0cd2dd4b53 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -15,11 +15,11 @@ */ package org.springframework.data.mongodb.repository.query; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.bson.Document; import org.reactivestreams.Publisher; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mongodb.core.MongoOperations; @@ -33,7 +33,7 @@ import org.springframework.data.mongodb.repository.query.ReactiveMongoQueryExecution.ResultProcessingConverter; import org.springframework.data.mongodb.repository.query.ReactiveMongoQueryExecution.ResultProcessingExecution; import org.springframework.data.repository.query.ParameterAccessor; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.util.TypeInformation; @@ -55,7 +55,7 @@ public abstract class AbstractReactiveMongoQuery implements RepositoryQuery { private final EntityInstantiators instantiators; private final FindWithProjection findOperationWithProjection; private final SpelExpressionParser expressionParser; - private final QueryMethodEvaluationContextProvider evaluationContextProvider; + private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; /** * Creates a new {@link AbstractReactiveMongoQuery} from the given {@link MongoQueryMethod} and @@ -67,12 +67,12 @@ public abstract class AbstractReactiveMongoQuery implements RepositoryQuery { * @param evaluationContextProvider must not be {@literal null}. */ public AbstractReactiveMongoQuery(ReactiveMongoQueryMethod method, ReactiveMongoOperations operations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + SpelExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { Assert.notNull(method, "MongoQueryMethod must not be null!"); Assert.notNull(operations, "ReactiveMongoOperations must not be null!"); Assert.notNull(expressionParser, "SpelExpressionParser must not be null!"); - Assert.notNull(evaluationContextProvider, "QueryMethodEvaluationContextProvider must not be null!"); + Assert.notNull(evaluationContextProvider, "ReactiveEvaluationContextExtension must not be null!"); this.method = method; this.operations = operations; @@ -98,25 +98,21 @@ public MongoQueryMethod getQueryMethod() { * (non-Javadoc) * @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[]) */ - public Object execute(Object[] parameters) { + public Publisher execute(Object[] parameters) { return method.hasReactiveWrapperParameter() ? executeDeferred(parameters) : execute(new MongoParametersParameterAccessor(method, parameters)); } @SuppressWarnings("unchecked") - private Object executeDeferred(Object[] parameters) { + private Publisher executeDeferred(Object[] parameters) { ReactiveMongoParameterAccessor parameterAccessor = new ReactiveMongoParameterAccessor(method, parameters); - if (getQueryMethod().isCollectionQuery()) { - return Flux.defer(() -> (Publisher) execute(parameterAccessor)); - } - - return Mono.defer(() -> (Mono) execute(parameterAccessor)); + return execute(parameterAccessor); } - private Object execute(MongoParameterAccessor parameterAccessor) { + private Publisher execute(MongoParameterAccessor parameterAccessor) { ConvertingParameterAccessor accessor = new ConvertingParameterAccessor(operations.getConverter(), parameterAccessor); @@ -141,24 +137,27 @@ private Object execute(MongoParameterAccessor parameterAccessor) { * @param accessor for providing invocation arguments. Never {@literal null}. * @param typeToRead the desired component target type. Can be {@literal null}. */ - protected Object doExecute(ReactiveMongoQueryMethod method, ResultProcessor processor, + protected Publisher doExecute(ReactiveMongoQueryMethod method, ResultProcessor processor, ConvertingParameterAccessor accessor, @Nullable Class typeToRead) { - Query query = createQuery(accessor); - applyQueryMetaAttributesWhenPresent(query); - query = applyAnnotatedDefaultSortIfPresent(query); - query = applyAnnotatedCollationIfPresent(query, accessor); + return createQuery(accessor).flatMapMany(it -> { + + Query query = it; + applyQueryMetaAttributesWhenPresent(query); + query = applyAnnotatedDefaultSortIfPresent(query); + query = applyAnnotatedCollationIfPresent(query, accessor); - FindWithQuery find = typeToRead == null // - ? findOperationWithProjection // - : findOperationWithProjection.as(typeToRead); + FindWithQuery find = typeToRead == null // + ? findOperationWithProjection // + : findOperationWithProjection.as(typeToRead); - String collection = method.getEntityInformation().getCollectionName(); + String collection = method.getEntityInformation().getCollectionName(); - ReactiveMongoQueryExecution execution = getExecution(accessor, - new ResultProcessingConverter(processor, operations, instantiators), find); - return execution.execute(query, processor.getReturnedType().getDomainType(), collection); + ReactiveMongoQueryExecution execution = getExecution(accessor, + new ResultProcessingConverter(processor, operations, instantiators), find); + return execution.execute(query, processor.getReturnedType().getDomainType(), collection); + }); } /** @@ -254,8 +253,8 @@ Query applyAnnotatedCollationIfPresent(Query query, ConvertingParameterAccessor * @param accessor must not be {@literal null}. * @return */ - protected Query createCountQuery(ConvertingParameterAccessor accessor) { - return applyQueryMetaAttributesWhenPresent(createQuery(accessor)); + protected Mono createCountQuery(ConvertingParameterAccessor accessor) { + return createQuery(accessor).map(this::applyQueryMetaAttributesWhenPresent); } /** @@ -264,7 +263,7 @@ protected Query createCountQuery(ConvertingParameterAccessor accessor) { * @param accessor must not be {@literal null}. * @return */ - protected abstract Query createQuery(ConvertingParameterAccessor accessor); + protected abstract Mono createQuery(ConvertingParameterAccessor accessor); /** * Returns whether the query should get a count projection applied. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index c77c37f65f..74d9c21530 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -72,8 +72,9 @@ static Collation computeCollation(@Nullable String collationExpression, Converti if (StringUtils.trimLeadingWhitespace(collationExpression).startsWith("{")) { - ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), - expressionParser, () -> evaluationContextProvider.getEvaluationContext(parameters, accessor.getValues())); + ParameterBindingContext bindingContext = ParameterBindingContext.forExpressions(accessor::getBindableValue, + expressionParser, dependencies -> evaluationContextProvider.getEvaluationContext(parameters, + accessor.getValues(), dependencies)); return Collation.from(CODEC.decode(collationExpression, bindingContext)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java new file mode 100644 index 0000000000..6dc63be9d2 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java @@ -0,0 +1,47 @@ +/* + * Copyright 2020 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 + * + * https://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.repository.query; + +import org.springframework.data.mapping.model.SpELExpressionEvaluator; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.ExpressionParser; + +/** + * Simple {@link SpELExpressionEvaluator} implementation using {@link ExpressionParser} and {@link EvaluationContext}. + * + * @author Mark Paluch + * @since 3.1 + */ +class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { + + private final ExpressionParser parser; + private final EvaluationContext context; + + DefaultSpELExpressionEvaluator(ExpressionParser parser, EvaluationContext context) { + this.parser = parser; + this.context = context; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.model.SpELExpressionEvaluator#evaluate(java.lang.String) + */ + @Override + @SuppressWarnings("unchecked") + public T evaluate(String expression) { + return (T) parser.parseExpression(expression).getValue(context, Object.class); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java new file mode 100644 index 0000000000..416c8fbbf1 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java @@ -0,0 +1,34 @@ +/* + * Copyright 2020 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 + * + * https://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.repository.query; + +import org.springframework.data.mapping.model.SpELExpressionEvaluator; + +/** + * {@link SpELExpressionEvaluator} that does not support SpEL evaluation. + * + * @author Mark Paluch + * @since 3.1 + */ +enum NoOpExpressionEvaluator implements SpELExpressionEvaluator { + + INSTANCE; + + @Override + public T evaluate(String expression) { + throw new UnsupportedOperationException("Expression evaluation not supported"); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index e2b9d51da0..2ca038ba89 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -48,7 +48,7 @@ */ interface ReactiveMongoQueryExecution { - Object execute(Query query, Class type, String collection); + Publisher execute(Query query, Class type, String collection); /** * {@link MongoQueryExecution} to execute geo-near queries. @@ -74,7 +74,7 @@ public GeoNearExecution(ReactiveMongoOperations operations, MongoParameterAccess * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) */ @Override - public Object execute(Query query, Class type, String collection) { + public Publisher execute(Query query, Class type, String collection) { Flux> results = doExecuteQuery(query, type, collection); return isStreamOfGeoResult() ? results : results.map(GeoResult::getContent); @@ -132,7 +132,7 @@ public DeleteExecution(ReactiveMongoOperations operations, MongoQueryMethod meth * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) */ @Override - public Object execute(Query query, Class type, String collection) { + public Publisher execute(Query query, Class type, String collection) { if (method.isCollectionQuery()) { return operations.findAllAndRemove(query, type, collection); @@ -166,8 +166,8 @@ public ResultProcessingExecution(ReactiveMongoQueryExecution delegate, Converter } @Override - public Object execute(Query query, Class type, String collection) { - return converter.convert(delegate.execute(query, type, collection)); + public Publisher execute(Query query, Class type, String collection) { + return (Publisher) converter.convert(delegate.execute(query, type, collection)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java index 0bce40c3cd..f2226f6b03 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.repository.query; +import reactor.core.publisher.Mono; + import org.bson.Document; import org.bson.json.JsonParseException; @@ -26,7 +28,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.TextCriteria; import org.springframework.data.repository.query.QueryMethod; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.repository.query.ReturnedType; @@ -57,7 +59,7 @@ public class ReactivePartTreeMongoQuery extends AbstractReactiveMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public ReactivePartTreeMongoQuery(ReactiveMongoQueryMethod method, ReactiveMongoOperations mongoOperations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + SpelExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); @@ -81,7 +83,7 @@ public PartTree getTree() { * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#createQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor, boolean) */ @Override - protected Query createQuery(ConvertingParameterAccessor accessor) { + protected Mono createQuery(ConvertingParameterAccessor accessor) { MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, context, isGeoNearQuery); Query query = creator.createQuery(); @@ -105,7 +107,7 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { returnedType.getInputProperties().forEach(query.fields()::include); } - return query; + return Mono.just(query); } try { @@ -113,7 +115,7 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { BasicQuery result = new BasicQuery(query.getQueryObject(), Document.parse(fieldSpec)); result.setSortObject(query.getSortObject()); - return result; + return Mono.just(result); } catch (JsonParseException o_O) { throw new IllegalStateException(String.format("Invalid query or field specification in %s!", getQueryMethod()), @@ -126,8 +128,8 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#createCountQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor) */ @Override - protected Query createCountQuery(ConvertingParameterAccessor accessor) { - return new MongoQueryCreator(tree, accessor, context, false).createQuery(); + protected Mono createCountQuery(ConvertingParameterAccessor accessor) { + return Mono.fromSupplier(() -> new MongoQueryCreator(tree, accessor, context, false).createQuery()); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java index 347df2fd22..8df312ec37 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java @@ -16,11 +16,16 @@ package org.springframework.data.mongodb.repository.query; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; import org.bson.Document; +import org.reactivestreams.Publisher; +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; @@ -29,8 +34,11 @@ import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.mongodb.util.json.ParameterBindingContext; +import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.spel.ExpressionDependencies; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.ClassUtils; @@ -44,8 +52,10 @@ */ public class ReactiveStringBasedAggregation extends AbstractReactiveMongoQuery { + private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); + private final SpelExpressionParser expressionParser; - private final QueryMethodEvaluationContextProvider evaluationContextProvider; + private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final ReactiveMongoOperations reactiveMongoOperations; private final MongoConverter mongoConverter; @@ -57,7 +67,7 @@ public class ReactiveStringBasedAggregation extends AbstractReactiveMongoQuery { */ public ReactiveStringBasedAggregation(ReactiveMongoQueryMethod method, ReactiveMongoOperations reactiveMongoOperations, SpelExpressionParser expressionParser, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, reactiveMongoOperations, expressionParser, evaluationContextProvider); @@ -72,52 +82,81 @@ public ReactiveStringBasedAggregation(ReactiveMongoQueryMethod method, * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#doExecute(org.springframework.data.mongodb.repository.query.ReactiveMongoQueryMethod, org.springframework.data.repository.query.ResultProcessor, org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor, java.lang.Class) */ @Override - protected Object doExecute(ReactiveMongoQueryMethod method, ResultProcessor processor, + protected Publisher doExecute(ReactiveMongoQueryMethod method, ResultProcessor processor, ConvertingParameterAccessor accessor, Class typeToRead) { - Class sourceType = method.getDomainClass(); - Class targetType = typeToRead; + return computePipeline(accessor).flatMapMany(it -> { - List pipeline = computePipeline(accessor); - AggregationUtils.appendSortIfPresent(pipeline, accessor, typeToRead); - AggregationUtils.appendLimitAndOffsetIfPresent(pipeline, accessor); + Class sourceType = method.getDomainClass(); + Class targetType = typeToRead; - boolean isSimpleReturnType = isSimpleReturnType(typeToRead); - boolean isRawReturnType = ClassUtils.isAssignable(org.bson.Document.class, typeToRead); + List pipeline = it; - if (isSimpleReturnType || isRawReturnType) { - targetType = Document.class; - } + AggregationUtils.appendSortIfPresent(pipeline, accessor, typeToRead); + AggregationUtils.appendLimitAndOffsetIfPresent(pipeline, accessor); - AggregationOptions options = computeOptions(method, accessor); - TypedAggregation aggregation = new TypedAggregation<>(sourceType, pipeline, options); + boolean isSimpleReturnType = isSimpleReturnType(typeToRead); + boolean isRawReturnType = ClassUtils.isAssignable(org.bson.Document.class, typeToRead); - Flux flux = reactiveMongoOperations.aggregate(aggregation, targetType); + if (isSimpleReturnType || isRawReturnType) { + targetType = Document.class; + } - if (isSimpleReturnType && !isRawReturnType) { - flux = flux.handle((it, sink) -> { + AggregationOptions options = computeOptions(method, accessor); + TypedAggregation aggregation = new TypedAggregation<>(sourceType, pipeline, options); - Object result = AggregationUtils.extractSimpleTypeResult((Document) it, typeToRead, mongoConverter); + Flux flux = reactiveMongoOperations.aggregate(aggregation, targetType); - if (result != null) { - sink.next(result); - } - }); - } + if (isSimpleReturnType && !isRawReturnType) { + flux = flux.handle((item, sink) -> { - if (method.isCollectionQuery()) { - return flux; - } else { - return flux.next(); - } + Object result = AggregationUtils.extractSimpleTypeResult((Document) item, typeToRead, mongoConverter); + + if (result != null) { + sink.next(result); + } + }); + } + + if (method.isCollectionQuery()) { + return flux; + } else { + return flux.next(); + } + }); } private boolean isSimpleReturnType(Class targetType) { return MongoSimpleTypes.HOLDER.isSimpleType(targetType); } - List computePipeline(ConvertingParameterAccessor accessor) { - return AggregationUtils.computePipeline(getQueryMethod(), accessor, expressionParser, evaluationContextProvider); + private Mono> computePipeline(ConvertingParameterAccessor accessor) { + + MongoQueryMethod method = getQueryMethod(); + + List> stages = new ArrayList<>(method.getAnnotatedAggregation().length); + + for (String source : method.getAnnotatedAggregation()) { + + Optional dependencies = CODEC.getExpressionDependencies(source, + accessor::getBindableValue, expressionParser); + + Mono evaluator = dependencies.map( + it -> evaluationContextProvider.getEvaluationContextLater(method.getParameters(), accessor.getValues(), it)) + .map(evaluationContext -> evaluationContext + .map(it -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, it))) + .orElseGet(() -> Mono.just(NoOpExpressionEvaluator.INSTANCE)); + + Mono stage = evaluator.map(it -> { + + ParameterBindingContext bindingContext = new ParameterBindingContext(accessor::getBindableValue, it); + + return ctx -> ctx.getMappedObject(CODEC.decode(source, bindingContext), method.getDomainClass()); + }); + stages.add(stage); + } + + return Flux.concat(stages).collectList(); } private AggregationOptions computeOptions(MongoQueryMethod method, ConvertingParameterAccessor accessor) { @@ -136,7 +175,7 @@ private AggregationOptions computeOptions(MongoQueryMethod method, ConvertingPar * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#createQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor) */ @Override - protected Query createQuery(ConvertingParameterAccessor accessor) { + protected Mono createQuery(ConvertingParameterAccessor accessor) { throw new UnsupportedOperationException("No query support for aggregation"); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index b84fca368b..d8a57f0e80 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -15,17 +15,25 @@ */ package org.springframework.data.mongodb.repository.query; +import reactor.core.publisher.Mono; + +import java.util.Optional; + import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.util.json.ParameterBindingContext; import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveExtensionAwareQueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; +import org.springframework.data.spel.ExpressionDependencies; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Assert; @@ -46,7 +54,7 @@ public class ReactiveStringBasedMongoQuery extends AbstractReactiveMongoQuery { private final String fieldSpec; private final SpelExpressionParser expressionParser; - private final QueryMethodEvaluationContextProvider evaluationContextProvider; + private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final boolean isCountQuery; private final boolean isExistsQuery; @@ -62,13 +70,14 @@ public class ReactiveStringBasedMongoQuery extends AbstractReactiveMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public ReactiveStringBasedMongoQuery(ReactiveMongoQueryMethod method, ReactiveMongoOperations mongoOperations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + SpelExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { this(method.getAnnotatedQuery(), method, mongoOperations, expressionParser, evaluationContextProvider); } /** * Creates a new {@link ReactiveStringBasedMongoQuery} for the given {@link String}, {@link MongoQueryMethod}, - * {@link MongoOperations}, {@link SpelExpressionParser} and {@link QueryMethodEvaluationContextProvider}. + * {@link MongoOperations}, {@link SpelExpressionParser} and + * {@link ReactiveExtensionAwareQueryMethodEvaluationContextProvider}. * * @param query must not be {@literal null}. * @param method must not be {@literal null}. @@ -77,7 +86,7 @@ public ReactiveStringBasedMongoQuery(ReactiveMongoQueryMethod method, ReactiveMo */ public ReactiveStringBasedMongoQuery(String query, ReactiveMongoQueryMethod method, ReactiveMongoOperations mongoOperations, SpelExpressionParser expressionParser, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); @@ -114,21 +123,39 @@ public ReactiveStringBasedMongoQuery(String query, ReactiveMongoQueryMethod meth * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#createQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor) */ @Override - protected Query createQuery(ConvertingParameterAccessor accessor) { + protected Mono createQuery(ConvertingParameterAccessor accessor) { - ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, - () -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); + Mono queryObject = getBindingContext(accessor, expressionParser, this.query) + .map(it -> CODEC.decode(this.query, it)); + Mono fieldsObject = getBindingContext(accessor, expressionParser, this.fieldSpec) + .map(it -> CODEC.decode(this.fieldSpec, it)); - Document queryObject = CODEC.decode(this.query, bindingContext); - Document fieldsObject = CODEC.decode(this.fieldSpec, bindingContext); + return queryObject.zipWith(fieldsObject).map(tuple -> { - Query query = new BasicQuery(queryObject, fieldsObject).with(accessor.getSort()); + Query query = new BasicQuery(tuple.getT1(), tuple.getT2()).with(accessor.getSort()); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Created query %s for %s fields.", query.getQueryObject(), query.getFieldsObject())); - } + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Created query %s for %s fields.", query.getQueryObject(), query.getFieldsObject())); + } + + return query; + }); + } + + private Mono getBindingContext(ConvertingParameterAccessor accessor, + ExpressionParser expressionParser, String json) { + + Optional dependencies = CODEC.getExpressionDependencies(json, accessor::getBindableValue, + expressionParser); + + Mono evaluator = dependencies + .map(it -> evaluationContextProvider.getEvaluationContextLater(getQueryMethod().getParameters(), + accessor.getValues(), it)) + .map(evaluationContext -> evaluationContext + .map(it -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, it))) + .orElseGet(() -> Mono.just(NoOpExpressionEvaluator.INSTANCE)); - return query; + return evaluator.map(it -> new ParameterBindingContext(accessor::getBindableValue, it)); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index 1eb4f66c31..c1a0c73437 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -15,16 +15,22 @@ */ package org.springframework.data.mongodb.repository.query; +import java.util.Optional; + import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.util.json.ParameterBindingContext; import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.spel.ExpressionDependencies; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Assert; @@ -122,11 +128,8 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati @Override protected Query createQuery(ConvertingParameterAccessor accessor) { - ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, - () -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues())); - - Document queryObject = codec.decode(this.query, bindingContext); - Document fieldsObject = codec.decode(this.fieldSpec, bindingContext); + Document queryObject = codec.decode(this.query, getBindingContext(accessor, expressionParser, this.query)); + Document fieldsObject = codec.decode(this.fieldSpec, getBindingContext(accessor, expressionParser, this.fieldSpec)); Query query = new BasicQuery(queryObject, fieldsObject).with(accessor.getSort()); @@ -137,6 +140,22 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { return query; } + private ParameterBindingContext getBindingContext(ConvertingParameterAccessor accessor, + ExpressionParser expressionParser, String json) { + + Optional dependencies = codec.getExpressionDependencies(json, accessor::getBindableValue, + expressionParser); + + SpELExpressionEvaluator evaluator = dependencies + .map(it -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), + accessor.getValues(), it)) + .map(evaluationContext -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, + evaluationContext)) + .orElse(NoOpExpressionEvaluator.INSTANCE); + + return new ParameterBindingContext(accessor::getBindableValue, evaluator); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#isCountQuery() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java index d6508e8a4c..6ab3ae0bb2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java @@ -42,6 +42,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; @@ -127,7 +128,8 @@ protected Object getTargetRepository(RepositoryInformation information) { @Override protected Optional getQueryLookupStrategy(@Nullable Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) { - return Optional.of(new MongoQueryLookupStrategy(operations, evaluationContextProvider, mappingContext)); + return Optional.of(new MongoQueryLookupStrategy(operations, + (ReactiveQueryMethodEvaluationContextProvider) evaluationContextProvider, mappingContext)); } /* @@ -157,11 +159,11 @@ private MongoEntityInformation getEntityInformation(Class doma private static class MongoQueryLookupStrategy implements QueryLookupStrategy { private final ReactiveMongoOperations operations; - private final QueryMethodEvaluationContextProvider evaluationContextProvider; + private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final MappingContext, MongoPersistentProperty> mappingContext; MongoQueryLookupStrategy(ReactiveMongoOperations operations, - QueryMethodEvaluationContextProvider evaluationContextProvider, + ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider, MappingContext, MongoPersistentProperty> mappingContext) { this.operations = operations; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java index cdbe54c6c4..cc646d9aeb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java @@ -16,13 +16,17 @@ package org.springframework.data.mongodb.repository.support; import java.io.Serializable; +import java.util.Optional; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.index.IndexOperationsAdapter; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveExtensionAwareQueryMethodEvaluationContextProvider; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -84,10 +88,7 @@ protected void setMappingContext(MappingContext mappingContext) { /* * (non-Javadoc) - * - * @see - * org.springframework.data.repository.support.RepositoryFactoryBeanSupport - * #createRepositoryFactory() + * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#createRepositoryFactory() */ @Override protected RepositoryFactorySupport createRepositoryFactory() { @@ -102,6 +103,16 @@ protected RepositoryFactorySupport createRepositoryFactory() { return factory; } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#createDefaultQueryMethodEvaluationContextProvider(ListableBeanFactory) + */ + @Override + protected Optional createDefaultQueryMethodEvaluationContextProvider( + ListableBeanFactory beanFactory) { + return Optional.of(new ReactiveExtensionAwareQueryMethodEvaluationContextProvider(beanFactory)); + } + /** * Creates and initializes a {@link RepositoryFactorySupport} instance. * @@ -114,10 +125,7 @@ protected RepositoryFactorySupport getFactoryInstance(ReactiveMongoOperations op /* * (non-Javadoc) - * - * @see - * org.springframework.data.repository.support.RepositoryFactoryBeanSupport - * #afterPropertiesSet() + * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#afterPropertiesSet() */ @Override public void afterPropertiesSet() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java index d2ce700751..519ff1dbd3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java @@ -15,8 +15,11 @@ */ package org.springframework.data.mongodb.util.json; +import java.util.function.Function; import java.util.function.Supplier; +import org.springframework.data.mapping.model.SpELExpressionEvaluator; +import org.springframework.data.spel.ExpressionDependencies; import org.springframework.data.util.Lazy; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; @@ -28,25 +31,21 @@ * To be used along with {@link ParameterBindingDocumentCodec#decode(String, ParameterBindingContext)}. * * @author Christoph Strobl + * @author Mark Paluch * @since 2.2 */ public class ParameterBindingContext { private final ValueProvider valueProvider; - private final SpelExpressionParser expressionParser; - private final Lazy evaluationContext; + private final SpELExpressionEvaluator expressionEvaluator; /** * @param valueProvider * @param expressionParser * @param evaluationContext - * @deprecated since 2.2.3 - Please use - * {@link #ParameterBindingContext(ValueProvider, SpelExpressionParser, Supplier)} instead. */ - @Deprecated public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser expressionParser, EvaluationContext evaluationContext) { - this(valueProvider, expressionParser, () -> evaluationContext); } @@ -59,9 +58,48 @@ public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser expressionParser, Supplier evaluationContext) { + this(valueProvider, new SpELExpressionEvaluator() { + @Override + public T evaluate(String expressionString) { + return (T) expressionParser.parseExpression(expressionString).getValue(evaluationContext.get(), Object.class); + } + }); + } + + /** + * @param valueProvider + * @param expressionEvaluator + * @since 3.1 + */ + public ParameterBindingContext(ValueProvider valueProvider, SpELExpressionEvaluator expressionEvaluator) { this.valueProvider = valueProvider; - this.expressionParser = expressionParser; - this.evaluationContext = evaluationContext instanceof Lazy ? (Lazy) evaluationContext : Lazy.of(evaluationContext); + this.expressionEvaluator = expressionEvaluator; + } + + /** + * Create a new {@link ParameterBindingContext} that is capable of expression parsing and can provide a + * {@link EvaluationContext} based on {@link ExpressionDependencies}. + * + * @param valueProvider + * @param expressionParser + * @param contextFunction + * @return + * @since 3.1 + */ + public static ParameterBindingContext forExpressions(ValueProvider valueProvider, + SpelExpressionParser expressionParser, Function contextFunction) { + + return new ParameterBindingContext(valueProvider, new SpELExpressionEvaluator() { + @Override + public T evaluate(String expressionString) { + + Expression expression = expressionParser.parseExpression(expressionString); + ExpressionDependencies dependencies = ExpressionDependencies.discover(expression); + EvaluationContext evaluationContext = contextFunction.apply(dependencies); + + return (T) expression.getValue(evaluationContext, Object.class); + } + }); } @Nullable @@ -71,17 +109,7 @@ public Object bindableValueForIndex(int index) { @Nullable public Object evaluateExpression(String expressionString) { - - Expression expression = expressionParser.parseExpression(expressionString); - return expression.getValue(getEvaluationContext(), Object.class); - } - - public EvaluationContext getEvaluationContext() { - return this.evaluationContext.get(); - } - - public SpelExpressionParser getExpressionParser() { - return expressionParser; + return expressionEvaluator.evaluate(expressionString); } public ValueProvider getValueProvider() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index 33eeee9bae..69a0fec2ce 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -24,6 +24,7 @@ import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import org.bson.AbstractBsonReader.State; @@ -39,7 +40,11 @@ import org.bson.codecs.*; import org.bson.codecs.configuration.CodecRegistry; import org.bson.json.JsonParseException; + +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.spel.EvaluationContextProvider; +import org.springframework.data.spel.ExpressionDependencies; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.NumberUtils; @@ -163,7 +168,7 @@ public void encode(final BsonWriter writer, final Document document, final Encod public Document decode(@Nullable String json, Object[] values) { return decode(json, new ParameterBindingContext((index) -> values[index], new SpelExpressionParser(), - () -> EvaluationContextProvider.DEFAULT.getEvaluationContext(values))); + EvaluationContextProvider.DEFAULT.getEvaluationContext(values))); } public Document decode(@Nullable String json, ParameterBindingContext bindingContext) { @@ -176,6 +181,51 @@ public Document decode(@Nullable String json, ParameterBindingContext bindingCon return this.decode(reader, DecoderContext.builder().build()); } + /** + * Determine {@link ExpressionDependencies} from Expressions that are nested in the {@code json} content. Returns + * {@link Optional#empty()} if {@code json} is empty or of it does not contain any SpEL expressions. + * + * @param json + * @param expressionParser + * @return a {@link Optional} containing merged {@link ExpressionDependencies} object if expressions were found, + * otherwise {@link Optional#empty()}. + * @since 3.1 + */ + public Optional getExpressionDependencies(@Nullable String json, ValueProvider valueProvider, + ExpressionParser expressionParser) { + + if (StringUtils.isEmpty(json)) { + return Optional.empty(); + } + + List dependencies = new ArrayList<>(); + + ParameterBindingContext context = new ParameterBindingContext(valueProvider, new SpELExpressionEvaluator() { + @Override + public T evaluate(String expression) { + + dependencies.add(ExpressionDependencies.discover(expressionParser.parseExpression(expression))); + + return (T) new Object(); + } + }); + + ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, context); + this.decode(reader, DecoderContext.builder().build()); + + if (dependencies.isEmpty()) { + return Optional.empty(); + } + + ExpressionDependencies result = ExpressionDependencies.empty(); + + for (ExpressionDependencies dependency : dependencies) { + result = result.mergeWith(dependency); + } + + return Optional.of(result); + } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Document decode(final BsonReader reader, final DecoderContext decoderContext) { @@ -349,4 +399,5 @@ private List readList(final BsonReader reader, final DecoderContext deco reader.readEndArray(); return list; } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index 22821a63dd..e0e1a61edd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -36,6 +36,7 @@ import org.bson.types.MaxKey; import org.bson.types.MinKey; import org.bson.types.ObjectId; + import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.expression.EvaluationContext; import org.springframework.expression.spel.standard.SpelExpressionParser; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index ef388005e9..09700dcfc1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -67,6 +67,7 @@ import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor; import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.reactivestreams.client.MongoClient; @@ -112,7 +113,7 @@ ReactiveMongoRepositoryFactory factory(ReactiveMongoOperations template, BeanFac factory.setRepositoryBaseClass(SimpleReactiveMongoRepository.class); factory.setBeanClassLoader(beanFactory.getClass().getClassLoader()); factory.setBeanFactory(beanFactory); - factory.setEvaluationContextProvider(QueryMethodEvaluationContextProvider.DEFAULT); + factory.setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT); return factory; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java index 072e1ba400..a69e2903dd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java @@ -45,6 +45,7 @@ import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactory; import org.springframework.data.mongodb.repository.support.SimpleReactiveMongoRepository; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ClassUtils; @@ -86,7 +87,7 @@ public void setUp() { factory.setRepositoryBaseClass(SimpleReactiveMongoRepository.class); factory.setBeanClassLoader(classLoader); factory.setBeanFactory(beanFactory); - factory.setEvaluationContextProvider(QueryMethodEvaluationContextProvider.DEFAULT); + factory.setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT); repository = factory.getRepository(ReactivePersonRepostitory.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java index bed41afb3c..23fbf8c131 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQueryUnitTests.java @@ -18,6 +18,9 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import java.lang.reflect.Method; import java.util.List; import java.util.Locale; @@ -48,7 +51,7 @@ import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveExtensionAwareQueryMethodEvaluationContextProvider; import org.springframework.expression.spel.standard.SpelExpressionParser; /** @@ -85,13 +88,16 @@ void setUp() { doReturn(executableFind).when(mongoOperationsMock).query(any()); doReturn(withQueryMock).when(executableFind).as(any()); doReturn(withQueryMock).when(withQueryMock).matching(any(Query.class)); + doReturn(Flux.empty()).when(withQueryMock).all(); + doReturn(Mono.empty()).when(withQueryMock).first(); + doReturn(Mono.empty()).when(withQueryMock).one(); } @Test // DATAMONGO-1854 void shouldApplyStaticAnnotatedCollation() { createQueryForMethod("findWithCollationUsingSpimpleStringValueByFirstName", String.class) // - .execute(new Object[] { "dalinar" }); + .executeBlocking(new Object[] { "dalinar" }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -103,7 +109,7 @@ void shouldApplyStaticAnnotatedCollation() { void shouldApplyStaticAnnotatedCollationAsDocument() { createQueryForMethod("findWithCollationUsingDocumentByFirstName", String.class) // - .execute(new Object[] { "dalinar" }); + .executeBlocking(new Object[] { "dalinar" }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -115,7 +121,7 @@ void shouldApplyStaticAnnotatedCollationAsDocument() { void shouldApplyDynamicAnnotatedCollationAsString() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // - .execute(new Object[] { "dalinar", "en_US" }); + .executeBlocking(new Object[] { "dalinar", "en_US" }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -127,7 +133,7 @@ void shouldApplyDynamicAnnotatedCollationAsString() { void shouldApplyDynamicAnnotatedCollationAsDocument() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // - .execute(new Object[] { "dalinar", new Document("locale", "en_US") }); + .executeBlocking(new Object[] { "dalinar", new Document("locale", "en_US") }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -139,7 +145,7 @@ void shouldApplyDynamicAnnotatedCollationAsDocument() { void shouldApplyDynamicAnnotatedCollationAsLocale() { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // - .execute(new Object[] { "dalinar", Locale.US }); + .executeBlocking(new Object[] { "dalinar", Locale.US }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -152,7 +158,7 @@ void shouldThrowExceptionOnNonParsableCollation() { assertThatIllegalArgumentException().isThrownBy(() -> { createQueryForMethod("findWithCollationUsingPlaceholderByFirstName", String.class, Object.class) // - .execute(new Object[] { "dalinar", 100 }); + .executeBlocking(new Object[] { "dalinar", 100 }); }); } @@ -160,7 +166,7 @@ void shouldThrowExceptionOnNonParsableCollation() { void shouldApplyDynamicAnnotatedCollationIn() { createQueryForMethod("findWithCollationUsingPlaceholderInDocumentByFirstName", String.class, String.class) // - .execute(new Object[] { "dalinar", "en_US" }); + .executeBlocking(new Object[] { "dalinar", "en_US" }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -173,7 +179,7 @@ void shouldApplyDynamicAnnotatedCollationWithMultiplePlaceholders() { createQueryForMethod("findWithCollationUsingPlaceholdersInDocumentByFirstName", String.class, String.class, int.class) // - .execute(new Object[] { "dalinar", "en_US", 2 }); + .executeBlocking(new Object[] { "dalinar", "en_US", 2 }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -186,7 +192,7 @@ void shouldApplyCollationParameter() { Collation collation = Collation.of("en_US"); createQueryForMethod("findWithCollationParameterByFirstName", String.class, Collation.class) // - .execute(new Object[] { "dalinar", collation }); + .executeBlocking(new Object[] { "dalinar", collation }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -198,7 +204,7 @@ void collationParameterShouldOverrideAnnotation() { Collation collation = Collation.of("de_AT"); createQueryForMethod("findWithWithCollationParameterAndAnnotationByFirstName", String.class, Collation.class) // - .execute(new Object[] { "dalinar", collation }); + .executeBlocking(new Object[] { "dalinar", collation }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -209,7 +215,7 @@ void collationParameterShouldOverrideAnnotation() { void collationParameterShouldNotBeAppliedWhenNullOverrideAnnotation() { createQueryForMethod("findWithWithCollationParameterAndAnnotationByFirstName", String.class, Collation.class) // - .execute(new Object[] { "dalinar", null }); + .executeBlocking(new Object[] { "dalinar", null }); ArgumentCaptor captor = ArgumentCaptor.forClass(Query.class); verify(withQueryMock).matching(captor.capture()); @@ -242,12 +248,17 @@ private static class ReactiveMongoQueryFake extends AbstractReactiveMongoQuery { private boolean isLimitingQuery; ReactiveMongoQueryFake(ReactiveMongoQueryMethod method, ReactiveMongoOperations operations) { - super(method, operations, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT); + super(method, operations, new SpelExpressionParser(), + ReactiveExtensionAwareQueryMethodEvaluationContextProvider.DEFAULT); } @Override - protected Query createQuery(ConvertingParameterAccessor accessor) { - return new BasicQuery("{'foo':'bar'}"); + protected Mono createQuery(ConvertingParameterAccessor accessor) { + return Mono.just(new BasicQuery("{'foo':'bar'}")); + } + + Object executeBlocking(Object[] parameters) { + return Flux.from(super.execute(parameters)).collectList().block(); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java index f899f3c68f..35fb113cbd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.*; import lombok.Value; +import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -55,6 +56,7 @@ import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.reactive.ReactiveCrudRepository; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; @@ -172,7 +174,7 @@ private AggregationInvocation executeAggregation(String name, Object... args) { ArgumentCaptor aggregationCaptor = ArgumentCaptor.forClass(TypedAggregation.class); ArgumentCaptor targetTypeCaptor = ArgumentCaptor.forClass(Class.class); - Object result = aggregation.execute(args); + Object result = Flux.from((Publisher) aggregation.execute(args)).blockLast(); verify(operations).aggregate(aggregationCaptor.capture(), targetTypeCaptor.capture()); @@ -186,7 +188,7 @@ private ReactiveStringBasedAggregation createAggregationForMethod(String name, C ReactiveMongoQueryMethod queryMethod = new ReactiveMongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class), factory, converter.getMappingContext()); return new ReactiveStringBasedAggregation(queryMethod, operations, PARSER, - QueryMethodEvaluationContextProvider.DEFAULT); + ReactiveQueryMethodEvaluationContextProvider.DEFAULT); } private List pipelineOf(AggregationInvocation invocation) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java index 72eb4548fb..19f1ae4851 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java @@ -48,7 +48,10 @@ import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveExtensionAwareQueryMethodEvaluationContextProvider; +import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; +import org.springframework.data.spel.spi.EvaluationContextExtension; +import org.springframework.data.spel.spi.ReactiveEvaluationContextExtension; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Base64Utils; @@ -83,7 +86,7 @@ public void bindsSimplePropertyCorrectly() throws Exception { ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastname", String.class); ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews"); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}"); assertThat(query.getQueryObject()).isEqualTo(reference.getQueryObject()); @@ -101,7 +104,7 @@ public void bindsComplexPropertyCorrectly() throws Exception { converter.write(address, dbObject); dbObject.remove(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); Document queryObject = new Document("address", dbObject); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery(queryObject); @@ -136,7 +139,7 @@ public void shouldSupportFindByParameterizedCriteriaAndFields() throws Exception ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByParameterizedCriteriaAndFields", Document.class, Map.class); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor).block(); assertThat(query.getQueryObject()) .isEqualTo(new BasicQuery("{ \"firstname\": \"first\", \"lastname\": \"last\"}").getQueryObject()); @@ -150,7 +153,7 @@ public void shouldParseQueryWithParametersInExpression() throws Exception { ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithParametersInExpression", int.class, int.class, int.class, int.class); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor).block(); assertThat(query.getQueryObject()) .isEqualTo(new BasicQuery("{$where: 'return this.date.getUTCMonth() == 3 && this.date.getUTCDay() == 4;'}") @@ -164,7 +167,7 @@ public void shouldParseJsonKeyReplacementCorrectly() throws Exception { String.class, String.class); ConvertingParameterAccessor parameterAccessor = StubParameterAccessor.getAccessor(converter, "key", "value"); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(parameterAccessor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(parameterAccessor).block(); assertThat(query.getQueryObject()).isEqualTo(new Document().append("key", "value")); } @@ -175,7 +178,7 @@ public void shouldSupportExpressionsInCustomQueries() throws Exception { ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews"); ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpression", String.class); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}"); assertThat(query.getQueryObject()).isEqualTo(reference.getQueryObject()); @@ -188,7 +191,7 @@ public void shouldSupportExpressionsInCustomQueriesWithNestedObject() throws Exc ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndNestedObject", boolean.class, String.class); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{ \"id\" : { \"$exists\" : true}}"); assertThat(query.getQueryObject()).isEqualTo(reference.getQueryObject()); @@ -201,7 +204,7 @@ public void shouldSupportExpressionsInCustomQueriesWithMultipleNestedObjects() t ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndMultipleNestedObjects", boolean.class, String.class, String.class); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery( "{ \"id\" : { \"$exists\" : true} , \"foo\" : 42 , \"bar\" : { \"$exists\" : false}}"); @@ -215,21 +218,43 @@ public void shouldSupportNonQuotedBinaryDataReplacement() throws Exception { ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, binaryData); ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAsBinary", byte[].class); - org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor); + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery( "{'lastname' : { '$binary' : '" + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + 0 + "'}}"); assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); } + @Test // DATAMONGO-1894 + void shouldConsiderReactiveSpelExtension() throws Exception { + + ReactiveExtensionAwareQueryMethodEvaluationContextProvider contextProvider = new ReactiveExtensionAwareQueryMethodEvaluationContextProvider( + Collections.singletonList(ReactiveSpelExtension.INSTANCE)); + + ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter); + ReactiveStringBasedMongoQuery mongoQuery = createQueryForMethod(contextProvider, "withReactiveSpelExtensions"); + + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor).block(); + org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{lastname: true}", "{project: true}"); + + assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); + } + private ReactiveStringBasedMongoQuery createQueryForMethod(String name, Class... parameters) throws Exception { + return createQueryForMethod(ReactiveQueryMethodEvaluationContextProvider.DEFAULT, name, parameters); + } + + private ReactiveStringBasedMongoQuery createQueryForMethod( + ReactiveQueryMethodEvaluationContextProvider contextProvider, String name, Class... parameters) + throws Exception { Method method = SampleRepository.class.getMethod(name, parameters); ProjectionFactory factory = new SpelAwareProxyProjectionFactory(); ReactiveMongoQueryMethod queryMethod = new ReactiveMongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class), factory, converter.getMappingContext()); + return new ReactiveStringBasedMongoQuery(queryMethod, operations, PARSER, - QueryMethodEvaluationContextProvider.DEFAULT); + contextProvider); } private interface SampleRepository extends Repository { @@ -269,5 +294,42 @@ private interface SampleRepository extends Repository { @Query(value = "{ 'lastname' : ?0 }", exists = true) Mono existsByLastname(String lastname); + + @Query(value = "{ 'lastname' : ?#{hasRole()} }", fields = "{project: ?#{hasRole()}}") + Mono withReactiveSpelExtensions(); + } + + public enum ReactiveSpelExtension implements ReactiveEvaluationContextExtension { + + INSTANCE; + + @Override + public Mono getExtension() { + return Mono.just(SpelExtension.INSTANCE); + } + + @Override + public String getExtensionId() { + return "sample"; + } + } + + public enum SpelExtension implements EvaluationContextExtension { + + INSTANCE; + + @Override + public Object getRootObject() { + return this; + } + + @Override + public String getExtensionId() { + return "sample"; + } + + public boolean hasRole() { + return true; + } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 3b1fb761cb..bc774538f2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -25,11 +25,13 @@ import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Optional; import org.bson.Document; import org.bson.codecs.DecoderContext; import org.junit.jupiter.api.Test; import org.springframework.data.spel.EvaluationContextProvider; +import org.springframework.data.spel.ExpressionDependencies; import org.springframework.expression.EvaluationContext; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -39,6 +41,7 @@ * Unit tests for {@link ParameterBindingJsonReader}. * * @author Christoph Strobl + * @author Mark Paluch */ class ParameterBindingJsonReaderUnitTests { @@ -260,6 +263,29 @@ void bindQuotedMulitParameterInArray() { .isEqualTo(new Document("name", new Document("$in", Collections.singletonList("dalinar,kohlin")))); } + @Test // DATAMONGO-1894 + void discoversNoDependenciesInExpression() { + + String json = "{ $and : [?#{ [0] == null ? { '$where' : 'true' } : { 'v1' : { '$in' : {[0]} } } }]}"; + + Optional expressionDependencies = new ParameterBindingDocumentCodec() + .getExpressionDependencies(json, it -> new Object(), new SpelExpressionParser()); + + assertThat(expressionDependencies).contains(ExpressionDependencies.empty()); + } + + @Test // DATAMONGO-1894 + void discoversCorrectlyDependenciesInExpression() { + + String json = "{ hello: ?#{hasRole('foo')} }"; + + Optional expressionDependencies = new ParameterBindingDocumentCodec() + .getExpressionDependencies(json, it -> new Object(), new SpelExpressionParser()); + + assertThat(expressionDependencies).isNotEmpty(); + assertThat(expressionDependencies.get()).hasSize(1); + } + @Test // DATAMONGO-2523 void bindSpelExpressionInArrayCorrectly/* closing bracket must not have leading whitespace! */() { From 41607b10d07e8c989705f7371aeb9bca4547b28f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 30 Jun 2020 14:38:07 +0200 Subject: [PATCH 0225/1381] DATAMONGO-1894 - Introduce cached ExpressionParser. Original Pull Request: #874 --- .../repository/query/AbstractMongoQuery.java | 5 +- .../query/AbstractReactiveMongoQuery.java | 5 +- .../repository/query/AggregationUtils.java | 7 ++- .../repository/query/CollationUtils.java | 3 +- .../query/DefaultSpELExpressionEvaluator.java | 25 ++++++++ .../query/NoOpExpressionEvaluator.java | 34 ----------- .../repository/query/PartTreeMongoQuery.java | 4 +- .../mongodb/repository/query/QueryUtils.java | 3 +- .../query/ReactivePartTreeMongoQuery.java | 3 +- .../query/ReactiveStringBasedAggregation.java | 13 ++-- .../query/ReactiveStringBasedMongoQuery.java | 8 +-- .../query/StringBasedAggregation.java | 6 +- .../query/StringBasedMongoQuery.java | 8 +-- .../support/CachingExpressionParser.java | 59 +++++++++++++++++++ .../support/MongoRepositoryFactory.java | 12 ++-- .../ReactiveMongoRepositoryFactory.java | 10 ++-- .../util/json/ParameterBindingContext.java | 5 +- src/main/asciidoc/new-features.adoc | 1 + .../reference/mongo-repositories.adoc | 22 +++---- 19 files changed, 147 insertions(+), 86 deletions(-) delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java index f3c7167b78..6c713d4446 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java @@ -30,6 +30,7 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -47,7 +48,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery { private final MongoQueryMethod method; private final MongoOperations operations; private final ExecutableFind executableFind; - private final SpelExpressionParser expressionParser; + private final ExpressionParser expressionParser; private final QueryMethodEvaluationContextProvider evaluationContextProvider; /** @@ -58,7 +59,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery { * @param expressionParser must not be {@literal null}. * @param evaluationContextProvider must not be {@literal null}. */ - public AbstractMongoQuery(MongoQueryMethod method, MongoOperations operations, SpelExpressionParser expressionParser, + public AbstractMongoQuery(MongoQueryMethod method, MongoOperations operations, ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { Assert.notNull(operations, "MongoOperations must not be null!"); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index 0cd2dd4b53..00294e2986 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -37,6 +37,7 @@ import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.util.TypeInformation; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -54,7 +55,7 @@ public abstract class AbstractReactiveMongoQuery implements RepositoryQuery { private final ReactiveMongoOperations operations; private final EntityInstantiators instantiators; private final FindWithProjection findOperationWithProjection; - private final SpelExpressionParser expressionParser; + private final ExpressionParser expressionParser; private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; /** @@ -67,7 +68,7 @@ public abstract class AbstractReactiveMongoQuery implements RepositoryQuery { * @param evaluationContextProvider must not be {@literal null}. */ public AbstractReactiveMongoQuery(ReactiveMongoQueryMethod method, ReactiveMongoOperations operations, - SpelExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { Assert.notNull(method, "MongoQueryMethod must not be null!"); Assert.notNull(operations, "ReactiveMongoOperations must not be null!"); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index e71306c358..6e77b95585 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -34,6 +34,7 @@ import org.springframework.data.mongodb.util.json.ParameterBindingContext; import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; @@ -64,12 +65,12 @@ private AggregationUtils() { * @param accessor must not be {@literal null}. * @return the {@link Query} having proper {@link Collation}. * @see AggregationOptions#getCollation() - * @see CollationUtils#computeCollation(String, ConvertingParameterAccessor, MongoParameters, SpelExpressionParser, + * @see CollationUtils#computeCollation(String, ConvertingParameterAccessor, MongoParameters, ExpressionParser, * QueryMethodEvaluationContextProvider) */ static AggregationOptions.Builder applyCollation(AggregationOptions.Builder builder, @Nullable String collationExpression, ConvertingParameterAccessor accessor, MongoParameters parameters, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { Collation collation = CollationUtils.computeCollation(collationExpression, accessor, parameters, expressionParser, evaluationContextProvider); @@ -119,7 +120,7 @@ static AggregationOptions.Builder applyMeta(AggregationOptions.Builder builder, * @return */ static List computePipeline(MongoQueryMethod method, ConvertingParameterAccessor accessor, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, () -> evaluationContextProvider.getEvaluationContext(method.getParameters(), accessor.getValues())); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index 74d9c21530..724cf2689d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -24,6 +24,7 @@ import org.springframework.data.mongodb.util.json.ParameterBindingContext; import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.NumberUtils; @@ -59,7 +60,7 @@ private CollationUtils() { */ @Nullable static Collation computeCollation(@Nullable String collationExpression, ConvertingParameterAccessor accessor, - MongoParameters parameters, SpelExpressionParser expressionParser, + MongoParameters parameters, ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { if (accessor.getCollation() != null) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java index 6dc63be9d2..ab4dcf8c8f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java @@ -35,6 +35,15 @@ class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { this.context = context; } + /** + * Return a {@link SpELExpressionEvaluator} that does not support expression evaluation. + * + * @return a {@link SpELExpressionEvaluator} that does not support expression evaluation. + */ + public static SpELExpressionEvaluator unsupported() { + return NoOpExpressionEvaluator.INSTANCE; + } + /* * (non-Javadoc) * @see org.springframework.data.mapping.model.SpELExpressionEvaluator#evaluate(java.lang.String) @@ -44,4 +53,20 @@ class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { public T evaluate(String expression) { return (T) parser.parseExpression(expression).getValue(context, Object.class); } + + /** + * {@link SpELExpressionEvaluator} that does not support SpEL evaluation. + * + * @author Mark Paluch + * @since 3.1 + */ + enum NoOpExpressionEvaluator implements SpELExpressionEvaluator { + + INSTANCE; + + @Override + public T evaluate(String expression) { + throw new UnsupportedOperationException("Expression evaluation not supported"); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java deleted file mode 100644 index 416c8fbbf1..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/NoOpExpressionEvaluator.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2020 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 - * - * https://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.repository.query; - -import org.springframework.data.mapping.model.SpELExpressionEvaluator; - -/** - * {@link SpELExpressionEvaluator} that does not support SpEL evaluation. - * - * @author Mark Paluch - * @since 3.1 - */ -enum NoOpExpressionEvaluator implements SpELExpressionEvaluator { - - INSTANCE; - - @Override - public T evaluate(String expression) { - throw new UnsupportedOperationException("Expression evaluation not supported"); - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java index 8063c17b24..902a364643 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java @@ -32,7 +32,7 @@ import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.repository.query.ReturnedType; import org.springframework.data.repository.query.parser.PartTree; -import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.ExpressionParser; import org.springframework.util.StringUtils; /** @@ -59,7 +59,7 @@ public class PartTreeMongoQuery extends AbstractMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public PartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java index b62891e3bc..5b68f79bfb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java @@ -21,6 +21,7 @@ import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; @@ -76,7 +77,7 @@ static Query decorateSort(Query query, Document defaultSort) { * @since 2.2 */ static Query applyCollation(Query query, @Nullable String collationExpression, ConvertingParameterAccessor accessor, - MongoParameters parameters, SpelExpressionParser expressionParser, + MongoParameters parameters, ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { Collation collation = CollationUtils.computeCollation(collationExpression, accessor, parameters, expressionParser, diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java index f2226f6b03..cb0f4cb613 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java @@ -33,6 +33,7 @@ import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.repository.query.ReturnedType; import org.springframework.data.repository.query.parser.PartTree; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.StringUtils; @@ -59,7 +60,7 @@ public class ReactivePartTreeMongoQuery extends AbstractReactiveMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public ReactivePartTreeMongoQuery(ReactiveMongoQueryMethod method, ReactiveMongoOperations mongoOperations, - SpelExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java index 8df312ec37..6ebdc61a2e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java @@ -39,6 +39,7 @@ import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.spel.ExpressionDependencies; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.ClassUtils; @@ -54,7 +55,7 @@ public class ReactiveStringBasedAggregation extends AbstractReactiveMongoQuery { private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); - private final SpelExpressionParser expressionParser; + private final ExpressionParser expressionParser; private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final ReactiveMongoOperations reactiveMongoOperations; private final MongoConverter mongoConverter; @@ -66,7 +67,7 @@ public class ReactiveStringBasedAggregation extends AbstractReactiveMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public ReactiveStringBasedAggregation(ReactiveMongoQueryMethod method, - ReactiveMongoOperations reactiveMongoOperations, SpelExpressionParser expressionParser, + ReactiveMongoOperations reactiveMongoOperations, ExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, reactiveMongoOperations, expressionParser, evaluationContextProvider); @@ -118,11 +119,7 @@ protected Publisher doExecute(ReactiveMongoQueryMethod method, ResultPro }); } - if (method.isCollectionQuery()) { - return flux; - } else { - return flux.next(); - } + return method.isCollectionQuery() ? flux : flux.next(); }); } @@ -145,7 +142,7 @@ private Mono> computePipeline(ConvertingParameterAcce it -> evaluationContextProvider.getEvaluationContextLater(method.getParameters(), accessor.getValues(), it)) .map(evaluationContext -> evaluationContext .map(it -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, it))) - .orElseGet(() -> Mono.just(NoOpExpressionEvaluator.INSTANCE)); + .orElseGet(() -> Mono.just(DefaultSpELExpressionEvaluator.unsupported())); Mono stage = evaluator.map(it -> { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index d8a57f0e80..360a09575b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -53,7 +53,7 @@ public class ReactiveStringBasedMongoQuery extends AbstractReactiveMongoQuery { private final String query; private final String fieldSpec; - private final SpelExpressionParser expressionParser; + private final ExpressionParser expressionParser; private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final boolean isCountQuery; @@ -70,7 +70,7 @@ public class ReactiveStringBasedMongoQuery extends AbstractReactiveMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public ReactiveStringBasedMongoQuery(ReactiveMongoQueryMethod method, ReactiveMongoOperations mongoOperations, - SpelExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { this(method.getAnnotatedQuery(), method, mongoOperations, expressionParser, evaluationContextProvider); } @@ -85,7 +85,7 @@ public ReactiveStringBasedMongoQuery(ReactiveMongoQueryMethod method, ReactiveMo * @param expressionParser must not be {@literal null}. */ public ReactiveStringBasedMongoQuery(String query, ReactiveMongoQueryMethod method, - ReactiveMongoOperations mongoOperations, SpelExpressionParser expressionParser, + ReactiveMongoOperations mongoOperations, ExpressionParser expressionParser, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); @@ -153,7 +153,7 @@ private Mono getBindingContext(ConvertingParameterAcces accessor.getValues(), it)) .map(evaluationContext -> evaluationContext .map(it -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, it))) - .orElseGet(() -> Mono.just(NoOpExpressionEvaluator.INSTANCE)); + .orElseGet(() -> Mono.just(DefaultSpELExpressionEvaluator.unsupported())); return evaluator.map(it -> new ParameterBindingContext(accessor::getBindableValue, it)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java index 912f0e3c9f..2dea1ff89b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java @@ -32,7 +32,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ResultProcessor; -import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.ExpressionParser; import org.springframework.util.ClassUtils; /** @@ -43,7 +43,7 @@ public class StringBasedAggregation extends AbstractMongoQuery { private final MongoOperations mongoOperations; private final MongoConverter mongoConverter; - private final SpelExpressionParser expressionParser; + private final ExpressionParser expressionParser; private final QueryMethodEvaluationContextProvider evaluationContextProvider; /** @@ -55,7 +55,7 @@ public class StringBasedAggregation extends AbstractMongoQuery { * @param evaluationContextProvider */ public StringBasedAggregation(MongoQueryMethod method, MongoOperations mongoOperations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); this.mongoOperations = mongoOperations; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index c1a0c73437..e09a7a1cd3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -54,7 +54,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery { private final String fieldSpec; private final ParameterBindingDocumentCodec codec; - private final SpelExpressionParser expressionParser; + private final ExpressionParser expressionParser; private final QueryMethodEvaluationContextProvider evaluationContextProvider; private final boolean isCountQuery; @@ -71,7 +71,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery { * @param evaluationContextProvider must not be {@literal null}. */ public StringBasedMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { this(method.getAnnotatedQuery(), method, mongoOperations, expressionParser, evaluationContextProvider); } @@ -85,7 +85,7 @@ public StringBasedMongoQuery(MongoQueryMethod method, MongoOperations mongoOpera * @param expressionParser must not be {@literal null}. */ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperations mongoOperations, - SpelExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { + ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { super(method, mongoOperations, expressionParser, evaluationContextProvider); @@ -151,7 +151,7 @@ private ParameterBindingContext getBindingContext(ConvertingParameterAccessor ac accessor.getValues(), it)) .map(evaluationContext -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, evaluationContext)) - .orElse(NoOpExpressionEvaluator.INSTANCE); + .orElse(DefaultSpELExpressionEvaluator.unsupported()); return new ParameterBindingContext(accessor::getBindableValue, evaluator); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java new file mode 100644 index 0000000000..318bb68749 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java @@ -0,0 +1,59 @@ +/* + * Copyright 2020 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 + * + * https://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.repository.support; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.ParseException; +import org.springframework.expression.ParserContext; + +/** + * Caching variant of {@link ExpressionParser}. This implementation does not support + * {@link #parseExpression(String, ParserContext) parsing with ParseContext}. + * + * @author Mark Paluch + * @since 3.1 + */ +class CachingExpressionParser implements ExpressionParser { + + private final ExpressionParser delegate; + private final Map cache = new ConcurrentHashMap<>(); + + public CachingExpressionParser(ExpressionParser delegate) { + this.delegate = delegate; + } + + /* + * (non-Javadoc) + * @see org.springframework.expression.ExpressionParser#parseExpression(java.lang.String) + */ + @Override + public Expression parseExpression(String expressionString) throws ParseException { + return cache.computeIfAbsent(expressionString, delegate::parseExpression); + } + + /* + * (non-Javadoc) + * @see org.springframework.expression.ExpressionParser#parseExpression(java.lang.String, org.springframework.expression.ParserContext) + */ + @Override + public Expression parseExpression(String expressionString, ParserContext context) throws ParseException { + throw new UnsupportedOperationException("Parsing using ParserContext is not supported"); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java index 1cbccff768..ea0ba55db1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java @@ -44,6 +44,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -162,7 +163,8 @@ private static class MongoQueryLookupStrategy implements QueryLookupStrategy { private final MongoOperations operations; private final QueryMethodEvaluationContextProvider evaluationContextProvider; - MappingContext, MongoPersistentProperty> mappingContext; + private final MappingContext, MongoPersistentProperty> mappingContext; + private final ExpressionParser expressionParser = new CachingExpressionParser(EXPRESSION_PARSER); public MongoQueryLookupStrategy(MongoOperations operations, QueryMethodEvaluationContextProvider evaluationContextProvider, @@ -186,14 +188,14 @@ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, if (namedQueries.hasQuery(namedQueryName)) { String namedQuery = namedQueries.getQuery(namedQueryName); - return new StringBasedMongoQuery(namedQuery, queryMethod, operations, EXPRESSION_PARSER, + return new StringBasedMongoQuery(namedQuery, queryMethod, operations, expressionParser, evaluationContextProvider); } else if (queryMethod.hasAnnotatedAggregation()) { - return new StringBasedAggregation(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); + return new StringBasedAggregation(queryMethod, operations, expressionParser, evaluationContextProvider); } else if (queryMethod.hasAnnotatedQuery()) { - return new StringBasedMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); + return new StringBasedMongoQuery(queryMethod, operations, expressionParser, evaluationContextProvider); } else { - return new PartTreeMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); + return new PartTreeMongoQuery(queryMethod, operations, expressionParser, evaluationContextProvider); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java index 6ab3ae0bb2..f55f6ed8fc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java @@ -44,6 +44,7 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -161,6 +162,7 @@ private static class MongoQueryLookupStrategy implements QueryLookupStrategy { private final ReactiveMongoOperations operations; private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final MappingContext, MongoPersistentProperty> mappingContext; + private final ExpressionParser expressionParser = new CachingExpressionParser(EXPRESSION_PARSER); MongoQueryLookupStrategy(ReactiveMongoOperations operations, ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider, @@ -184,15 +186,15 @@ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, if (namedQueries.hasQuery(namedQueryName)) { String namedQuery = namedQueries.getQuery(namedQueryName); - return new ReactiveStringBasedMongoQuery(namedQuery, queryMethod, operations, EXPRESSION_PARSER, + return new ReactiveStringBasedMongoQuery(namedQuery, queryMethod, operations, expressionParser, evaluationContextProvider); } else if (queryMethod.hasAnnotatedAggregation()) { - return new ReactiveStringBasedAggregation(queryMethod, operations, EXPRESSION_PARSER, + return new ReactiveStringBasedAggregation(queryMethod, operations, expressionParser, evaluationContextProvider); } else if (queryMethod.hasAnnotatedQuery()) { - return new ReactiveStringBasedMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); + return new ReactiveStringBasedMongoQuery(queryMethod, operations, expressionParser, evaluationContextProvider); } else { - return new ReactivePartTreeMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); + return new ReactivePartTreeMongoQuery(queryMethod, operations, expressionParser, evaluationContextProvider); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java index 519ff1dbd3..73900d456f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java @@ -23,6 +23,7 @@ import org.springframework.data.util.Lazy; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; @@ -55,7 +56,7 @@ public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser * @param evaluationContext a {@link Supplier} for {@link Lazy} context retrieval. * @since 2.2.3 */ - public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser expressionParser, + public ParameterBindingContext(ValueProvider valueProvider, ExpressionParser expressionParser, Supplier evaluationContext) { this(valueProvider, new SpELExpressionEvaluator() { @@ -87,7 +88,7 @@ public ParameterBindingContext(ValueProvider valueProvider, SpELExpressionEvalua * @since 3.1 */ public static ParameterBindingContext forExpressions(ValueProvider valueProvider, - SpelExpressionParser expressionParser, Function contextFunction) { + ExpressionParser expressionParser, Function contextFunction) { return new ParameterBindingContext(valueProvider, new SpELExpressionEvaluator() { @Override diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index d0c9317f81..c773caa890 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,6 +5,7 @@ == What's New in Spring Data MongoDB 3.1 * <> enabled through `@EnableReactiveMongoAuditing`. `@EnableMongoAuditing` no longer registers `ReactiveAuditingEntityCallback`. +* Reactive SpEL support in `@Query` and `@Aggregation` query methods. [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index 48724e2b8a..328a547b5a 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -131,7 +131,7 @@ The preceding example creates an application context with Spring's unit test sup [[mongodb.repositories.queries]] == Query Methods -Most of the data access operations you usually trigger on a repository result in a query being executed against the MongoDB databases. Defining such a query is a matter of declaring a method on the repository interface, as the following example shows: +Most of the data access operations you usually trigger on a repository result in a query being executed against the MongoDB databases.Defining such a query is a matter of declaring a method on the repository interface, as the following example shows: .PersonRepository with query methods ==== @@ -445,7 +445,7 @@ results in `{ age : -1 }`. Using `Sort.by(ASC, "age")` overrides the defaults an Query strings and field definitions can be used together with SpEL expressions to create dynamic queries at runtime. SpEL expressions can provide predicate values and can be used to extend predicates with subdocuments. -Expressions expose method arguments through an array that contains all the arguments. The following query uses `[0]` +Expressions expose method arguments through an array that contains all the arguments.The following query uses `[0]` to declare the predicate value for `lastname` (which is equivalent to the `?0` parameter binding): [source,java] @@ -457,7 +457,7 @@ public interface PersonRepository extends MongoRepository { } ---- -Expressions can be used to invoke functions, evaluate conditionals, and construct values. SpEL expressions +Expressions can be used to invoke functions, evaluate conditionals, and construct values.SpEL expressions used in conjunction with JSON reveal a side-effect, because Map-like declarations inside of SpEL read like JSON, as the following example shows: [source,java] @@ -469,12 +469,12 @@ public interface PersonRepository extends MongoRepository { } ---- -SpEL in query strings can be a powerful way to enhance queries. However, they can also accept a broad range of unwanted arguments. +SpEL in query strings can be a powerful way to enhance queries.However, they can also accept a broad range of unwanted arguments. You should make sure to sanitize strings before passing them to the query to avoid unwanted changes to your query. Expression support is extensible through the Query SPI: `org.springframework.data.repository.query.spi.EvaluationContextExtension`. -The Query SPI can contribute properties and functions and can customize the root object. Extensions are retrieved from the application context -at the time of SpEL evaluation when the query is built. The following example shows how to use `EvaluationContextExtension`: +The Query SPI can contribute properties and functions and can customize the root object.Extensions are retrieved from the application context +at the time of SpEL evaluation when the query is built.The following example shows how to use `EvaluationContextExtension`: [source,java] ---- @@ -492,13 +492,15 @@ public class SampleEvaluationContextExtension extends EvaluationContextExtension } ---- -NOTE: Bootstrapping `MongoRepositoryFactory` yourself is not application context-aware and requires further configuration -to pick up Query SPI extensions. +NOTE: Bootstrapping `MongoRepositoryFactory` yourself is not application context-aware and requires further configuration to pick up Query SPI extensions. + +NOTE: Reactive query methods can make use of `org.springframework.data.spel.spi.ReactiveEvaluationContextExtension`. [[mongodb.repositories.queries.type-safe]] === Type-safe Query Methods -MongoDB repository support integrates with the http://www.querydsl.com/[Querydsl] project, which provides a way to perform type-safe queries. To quote from the project description, "Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API." It provides the following features: +MongoDB repository support integrates with the http://www.querydsl.com/[Querydsl] project, which provides a way to perform type-safe queries. +To quote from the project description, "Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API." It provides the following features: * Code completion in the IDE (all properties, methods, and operations can be expanded in your favorite Java IDE). * Almost no syntactically invalid queries allowed (type-safe on all levels). @@ -519,7 +521,7 @@ Page page = repository.findAll(person.lastname.contains("a"), PageRequest.of(0, 2, Direction.ASC, "lastname")); ---- -`QPerson` is a class that is generated by the Java annotation post-processing tool. It is a `Predicate` that lets you write type-safe queries. Notice that there are no strings in the query other than the `C0123` value. +`QPerson` is a class that is generated by the Java annotation post-processing tool.It is a `Predicate` that lets you write type-safe queries.Notice that there are no strings in the query other than the `C0123` value. You can use the generated `Predicate` class by using the `QuerydslPredicateExecutor` interface, which the following listing shows: From 873fffa202db778dfb27b2bd48b2375f4b46f853 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 21 Jul 2020 12:25:45 +0200 Subject: [PATCH 0226/1381] DATAMONGO-1894 - Polishing. Remove superfluous Optional wrappers and unify SpEL dependency resolution. Original Pull Request: #874 --- .../query/AbstractReactiveMongoQuery.java | 23 ++++++- .../query/DefaultSpELExpressionEvaluator.java | 1 + .../query/ReactivePartTreeMongoQuery.java | 35 +++++----- .../query/ReactiveStringBasedAggregation.java | 14 +--- .../query/ReactiveStringBasedMongoQuery.java | 16 +---- .../query/StringBasedMongoQuery.java | 13 +--- .../support/CachingExpressionParser.java | 2 +- .../json/ParameterBindingDocumentCodec.java | 67 ++++++++++--------- ...tractPersonRepositoryIntegrationTests.java | 7 ++ .../ParameterBindingJsonReaderUnitTests.java | 11 ++- 10 files changed, 99 insertions(+), 90 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index 00294e2986..a0d8e87807 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -19,9 +19,9 @@ import org.bson.Document; import org.reactivestreams.Publisher; - import org.springframework.core.convert.converter.Converter; import org.springframework.data.mapping.model.EntityInstantiators; +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithProjection; import org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithQuery; @@ -36,9 +36,9 @@ import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.spel.ExpressionDependencies; import org.springframework.data.util.TypeInformation; import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -141,7 +141,6 @@ private Publisher execute(MongoParameterAccessor parameterAccessor) { protected Publisher doExecute(ReactiveMongoQueryMethod method, ResultProcessor processor, ConvertingParameterAccessor accessor, @Nullable Class typeToRead) { - return createQuery(accessor).flatMapMany(it -> { Query query = it; @@ -296,4 +295,22 @@ protected Mono createCountQuery(ConvertingParameterAccessor accessor) { * @since 2.0.4 */ protected abstract boolean isLimiting(); + + /** + * Obtain a {@link Mono publisher} emitting the {@link SpELExpressionEvaluator} suitable to evaluate expressions + * backed by the given dependencies. + * + * @param dependencies must not be {@literal null}. + * @param accessor must not be {@literal null}. + * @return a {@link Mono} emitting the {@link SpELExpressionEvaluator} when ready. + */ + protected Mono getSpelEvaluatorFor(ExpressionDependencies dependencies, + ConvertingParameterAccessor accessor) { + + return evaluationContextProvider + .getEvaluationContextLater(getQueryMethod().getParameters(), accessor.getValues(), dependencies) + .map(evaluationContext -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, + evaluationContext)) + .defaultIfEmpty(DefaultSpELExpressionEvaluator.unsupported()); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java index ab4dcf8c8f..cd154b5bd7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java @@ -39,6 +39,7 @@ class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { * Return a {@link SpELExpressionEvaluator} that does not support expression evaluation. * * @return a {@link SpELExpressionEvaluator} that does not support expression evaluation. + * @since 3.1 */ public static SpELExpressionEvaluator unsupported() { return NoOpExpressionEvaluator.INSTANCE; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java index cb0f4cb613..8ac8dbad1b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java @@ -19,7 +19,6 @@ import org.bson.Document; import org.bson.json.JsonParseException; - import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.ReactiveMongoOperations; @@ -34,7 +33,6 @@ import org.springframework.data.repository.query.ReturnedType; import org.springframework.data.repository.query.parser.PartTree; import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.StringUtils; /** @@ -85,10 +83,27 @@ public PartTree getTree() { */ @Override protected Mono createQuery(ConvertingParameterAccessor accessor) { + return Mono.fromSupplier(() -> createQueryInternal(accessor, false)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#createCountQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor) + */ + @Override + protected Mono createCountQuery(ConvertingParameterAccessor accessor) { + return Mono.fromSupplier(() -> createQueryInternal(accessor, true)); + } + + private Query createQueryInternal(ConvertingParameterAccessor accessor, boolean isCountQuery) { - MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, context, isGeoNearQuery); + MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, context, isCountQuery ? false : isGeoNearQuery); Query query = creator.createQuery(); + if (isCountQuery) { + return query; + } + if (tree.isLimiting()) { query.limit(tree.getMaxResults()); } @@ -108,7 +123,7 @@ protected Mono createQuery(ConvertingParameterAccessor accessor) { returnedType.getInputProperties().forEach(query.fields()::include); } - return Mono.just(query); + return query; } try { @@ -116,23 +131,13 @@ protected Mono createQuery(ConvertingParameterAccessor accessor) { BasicQuery result = new BasicQuery(query.getQueryObject(), Document.parse(fieldSpec)); result.setSortObject(query.getSortObject()); - return Mono.just(result); - + return result; } catch (JsonParseException o_O) { throw new IllegalStateException(String.format("Invalid query or field specification in %s!", getQueryMethod()), o_O); } } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#createCountQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor) - */ - @Override - protected Mono createCountQuery(ConvertingParameterAccessor accessor) { - return Mono.fromSupplier(() -> new MongoQueryCreator(tree, accessor, context, false).createQuery()); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#isCountQuery() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java index 6ebdc61a2e..df9608eae6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java @@ -20,12 +20,9 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import org.bson.Document; import org.reactivestreams.Publisher; - -import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; @@ -40,7 +37,6 @@ import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.spel.ExpressionDependencies; import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.ClassUtils; /** @@ -135,16 +131,10 @@ private Mono> computePipeline(ConvertingParameterAcce for (String source : method.getAnnotatedAggregation()) { - Optional dependencies = CODEC.getExpressionDependencies(source, + ExpressionDependencies dependencies = CODEC.captureExpressionDependencies(source, accessor::getBindableValue, expressionParser); - Mono evaluator = dependencies.map( - it -> evaluationContextProvider.getEvaluationContextLater(method.getParameters(), accessor.getValues(), it)) - .map(evaluationContext -> evaluationContext - .map(it -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, it))) - .orElseGet(() -> Mono.just(DefaultSpELExpressionEvaluator.unsupported())); - - Mono stage = evaluator.map(it -> { + Mono stage = getSpelEvaluatorFor(dependencies, accessor).map(it -> { ParameterBindingContext bindingContext = new ParameterBindingContext(accessor::getBindableValue, it); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index 360a09575b..1ab7762d38 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -17,13 +17,9 @@ import reactor.core.publisher.Mono; -import java.util.Optional; - import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; @@ -145,17 +141,11 @@ protected Mono createQuery(ConvertingParameterAccessor accessor) { private Mono getBindingContext(ConvertingParameterAccessor accessor, ExpressionParser expressionParser, String json) { - Optional dependencies = CODEC.getExpressionDependencies(json, accessor::getBindableValue, + ExpressionDependencies dependencies = CODEC.captureExpressionDependencies(json, accessor::getBindableValue, expressionParser); - Mono evaluator = dependencies - .map(it -> evaluationContextProvider.getEvaluationContextLater(getQueryMethod().getParameters(), - accessor.getValues(), it)) - .map(evaluationContext -> evaluationContext - .map(it -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, it))) - .orElseGet(() -> Mono.just(DefaultSpELExpressionEvaluator.unsupported())); - - return evaluator.map(it -> new ParameterBindingContext(accessor::getBindableValue, it)); + return getSpelEvaluatorFor(dependencies, accessor) + .map(it -> new ParameterBindingContext(accessor::getBindableValue, it)); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index e09a7a1cd3..bb6864233c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -15,13 +15,10 @@ */ package org.springframework.data.mongodb.repository.query; -import java.util.Optional; - import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; @@ -143,15 +140,11 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { private ParameterBindingContext getBindingContext(ConvertingParameterAccessor accessor, ExpressionParser expressionParser, String json) { - Optional dependencies = codec.getExpressionDependencies(json, accessor::getBindableValue, + ExpressionDependencies dependencies = codec.captureExpressionDependencies(json, accessor::getBindableValue, expressionParser); - SpELExpressionEvaluator evaluator = dependencies - .map(it -> evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(), - accessor.getValues(), it)) - .map(evaluationContext -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, - evaluationContext)) - .orElse(DefaultSpELExpressionEvaluator.unsupported()); + SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(expressionParser, evaluationContextProvider + .getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues(), dependencies)); return new ParameterBindingContext(accessor::getBindableValue, evaluator); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java index 318bb68749..a30833b4d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java @@ -35,7 +35,7 @@ class CachingExpressionParser implements ExpressionParser { private final ExpressionParser delegate; private final Map cache = new ConcurrentHashMap<>(); - public CachingExpressionParser(ExpressionParser delegate) { + CachingExpressionParser(ExpressionParser delegate) { this.delegate = delegate; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index 69a0fec2ce..566ff603a5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -40,7 +40,6 @@ import org.bson.codecs.*; import org.bson.codecs.configuration.CodecRegistry; import org.bson.json.JsonParseException; - import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.spel.ExpressionDependencies; @@ -187,43 +186,23 @@ public Document decode(@Nullable String json, ParameterBindingContext bindingCon * * @param json * @param expressionParser - * @return a {@link Optional} containing merged {@link ExpressionDependencies} object if expressions were found, - * otherwise {@link Optional#empty()}. + * @return merged {@link ExpressionDependencies} object if expressions were found, otherwise + * {@link ExpressionDependencies#none()}. * @since 3.1 */ - public Optional getExpressionDependencies(@Nullable String json, ValueProvider valueProvider, + public ExpressionDependencies captureExpressionDependencies(@Nullable String json, ValueProvider valueProvider, ExpressionParser expressionParser) { if (StringUtils.isEmpty(json)) { - return Optional.empty(); + return ExpressionDependencies.none(); } - List dependencies = new ArrayList<>(); - - ParameterBindingContext context = new ParameterBindingContext(valueProvider, new SpELExpressionEvaluator() { - @Override - public T evaluate(String expression) { - - dependencies.add(ExpressionDependencies.discover(expressionParser.parseExpression(expression))); - - return (T) new Object(); - } - }); - - ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, context); - this.decode(reader, DecoderContext.builder().build()); + DependencyCapturingExpressionEvaluator expressionEvaluator = new DependencyCapturingExpressionEvaluator( + expressionParser); + this.decode(new ParameterBindingJsonReader(json, new ParameterBindingContext(valueProvider, expressionEvaluator)), + DecoderContext.builder().build()); - if (dependencies.isEmpty()) { - return Optional.empty(); - } - - ExpressionDependencies result = ExpressionDependencies.empty(); - - for (ExpressionDependencies dependency : dependencies) { - result = result.mergeWith(dependency); - } - - return Optional.of(result); + return expressionEvaluator.getCapturedDependencies(); } @SuppressWarnings({ "rawtypes", "unchecked" }) @@ -400,4 +379,32 @@ private List readList(final BsonReader reader, final DecoderContext deco return list; } + /** + * @author Christoph Strobl + * @since 3.1 + */ + static class DependencyCapturingExpressionEvaluator implements SpELExpressionEvaluator { + + private static final Object PLACEHOLDER = new Object(); + + private final ExpressionParser expressionParser; + private final List dependencies = new ArrayList<>(); + + DependencyCapturingExpressionEvaluator(ExpressionParser expressionParser) { + this.expressionParser = expressionParser; + } + + @Nullable + @Override + public T evaluate(String expression) { + + dependencies.add(ExpressionDependencies.discover(expressionParser.parseExpression(expression))); + return (T) PLACEHOLDER; + } + + ExpressionDependencies getCapturedDependencies() { + return ExpressionDependencies.merged(dependencies); + } + + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index cd41e8ffa5..a1ec0957c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -1356,4 +1356,11 @@ void findWithMoreThan10Arguments() { this.alicia.getEmail(), this.alicia.getAge(), Sex.FEMALE, this.alicia.createdAt, alicia.getSkills(), "street", "zipCode", "city", alicia.getUniqueId(), credentials.username, credentials.password)).isNotNull(); } + + @Test // DATAMONGO-1894 + void spelExpressionArgumentsGetReevaluatedOnEveryInvocation() { + + assertThat(repository.findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly("Dave")).containsExactly(dave); + assertThat(repository.findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly("Carter")).containsExactly(carter); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index bc774538f2..3403f304dc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -25,7 +25,6 @@ import java.util.Collections; import java.util.Date; import java.util.List; -import java.util.Optional; import org.bson.Document; import org.bson.codecs.DecoderContext; @@ -268,10 +267,10 @@ void discoversNoDependenciesInExpression() { String json = "{ $and : [?#{ [0] == null ? { '$where' : 'true' } : { 'v1' : { '$in' : {[0]} } } }]}"; - Optional expressionDependencies = new ParameterBindingDocumentCodec() - .getExpressionDependencies(json, it -> new Object(), new SpelExpressionParser()); + ExpressionDependencies expressionDependencies = new ParameterBindingDocumentCodec() + .captureExpressionDependencies(json, it -> new Object(), new SpelExpressionParser()); - assertThat(expressionDependencies).contains(ExpressionDependencies.empty()); + assertThat(expressionDependencies).isEqualTo(ExpressionDependencies.none()); } @Test // DATAMONGO-1894 @@ -279,8 +278,8 @@ void discoversCorrectlyDependenciesInExpression() { String json = "{ hello: ?#{hasRole('foo')} }"; - Optional expressionDependencies = new ParameterBindingDocumentCodec() - .getExpressionDependencies(json, it -> new Object(), new SpelExpressionParser()); + ExpressionDependencies expressionDependencies = new ParameterBindingDocumentCodec() + .captureExpressionDependencies(json, it -> new Object(), new SpelExpressionParser()); assertThat(expressionDependencies).isNotEmpty(); assertThat(expressionDependencies.get()).hasSize(1); From 0085c8063a888b8fe62528743e988c8da23fb574 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 23 Jul 2020 13:12:06 +0200 Subject: [PATCH 0227/1381] DATAMONGO-2557 - Use configured CodecRegistry when parsing String based queries instead of default one. Original pull request: #879. --- .../repository/query/AbstractMongoQuery.java | 34 ++++++++++++- .../query/AbstractReactiveMongoQuery.java | 51 +++++++++++++------ .../repository/query/AggregationUtils.java | 36 +------------ .../query/ReactiveStringBasedAggregation.java | 32 ++++++------ .../query/ReactiveStringBasedMongoQuery.java | 30 ++++++----- .../query/StringBasedAggregation.java | 31 +++++++++-- .../query/StringBasedMongoQuery.java | 27 ++++------ ...activeStringBasedAggregationUnitTests.java | 11 ++++ ...eactiveStringBasedMongoQueryUnitTests.java | 4 ++ .../StringBasedAggregationUnitTests.java | 13 +++++ .../query/StringBasedMongoQueryUnitTests.java | 4 ++ 11 files changed, 173 insertions(+), 100 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java index 6c713d4446..e74e7d64ba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java @@ -16,6 +16,8 @@ package org.springframework.data.mongodb.repository.query; import org.bson.Document; +import org.bson.codecs.configuration.CodecRegistry; +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; import org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind; @@ -30,11 +32,14 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.spel.ExpressionDependencies; +import org.springframework.expression.EvaluationContext; import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import com.mongodb.client.MongoDatabase; + /** * Base class for {@link RepositoryQuery} implementations for Mongo. * @@ -209,6 +214,29 @@ protected Query createCountQuery(ConvertingParameterAccessor accessor) { return applyQueryMetaAttributesWhenPresent(createQuery(accessor)); } + /** + * Obtain a the {@link EvaluationContext} suitable to evaluate expressions backed by the given dependencies. + * + * @param dependencies must not be {@literal null}. + * @param accessor must not be {@literal null}. + * @return the {@link SpELExpressionEvaluator}. + * @since 2.4 + */ + protected SpELExpressionEvaluator getSpELExpressionEvaluatorFor(ExpressionDependencies dependencies, + ConvertingParameterAccessor accessor) { + + return new DefaultSpELExpressionEvaluator(expressionParser, evaluationContextProvider + .getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues(), dependencies)); + } + + /** + * @return the {@link CodecRegistry} used. + * @since 2.4 + */ + protected CodecRegistry getCodecRegistry() { + return operations.execute(AbstractMongoQuery::obtainCodecRegistry); + } + /** * Creates a {@link Query} instance using the given {@link ParameterAccessor} * @@ -247,4 +275,8 @@ protected Query createCountQuery(ConvertingParameterAccessor accessor) { * @since 2.0.4 */ protected abstract boolean isLimiting(); + + private static CodecRegistry obtainCodecRegistry(MongoDatabase db) { + return db.getCodecRegistry(); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index a0d8e87807..aba7a46c2b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -18,6 +18,7 @@ import reactor.core.publisher.Mono; import org.bson.Document; +import org.bson.codecs.configuration.CodecRegistry; import org.reactivestreams.Publisher; import org.springframework.core.convert.converter.Converter; import org.springframework.data.mapping.model.EntityInstantiators; @@ -42,6 +43,9 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import com.mongodb.MongoClientSettings; +import com.mongodb.reactivestreams.client.MongoDatabase; + /** * Base class for reactive {@link RepositoryQuery} implementations for MongoDB. * @@ -257,6 +261,35 @@ protected Mono createCountQuery(ConvertingParameterAccessor accessor) { return createQuery(accessor).map(this::applyQueryMetaAttributesWhenPresent); } + /** + * Obtain a {@link Mono publisher} emitting the {@link SpELExpressionEvaluator} suitable to evaluate expressions + * backed by the given dependencies. + * + * @param dependencies must not be {@literal null}. + * @param accessor must not be {@literal null}. + * @return a {@link Mono} emitting the {@link SpELExpressionEvaluator} when ready. + * @since 2.4 + */ + protected Mono getSpelEvaluatorFor(ExpressionDependencies dependencies, + ConvertingParameterAccessor accessor) { + + return evaluationContextProvider + .getEvaluationContextLater(getQueryMethod().getParameters(), accessor.getValues(), dependencies) + .map(evaluationContext -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, + evaluationContext)) + .defaultIfEmpty(DefaultSpELExpressionEvaluator.unsupported()); + } + + /** + * @return a {@link Mono} emitting the {@link CodecRegistry} when ready. + * @since 2.4 + */ + protected Mono getCodecRegistry() { + + return Mono.from(operations.execute(AbstractReactiveMongoQuery::obtainCodecRegistry)) + .defaultIfEmpty(MongoClientSettings.getDefaultCodecRegistry()); + } + /** * Creates a {@link Query} instance using the given {@link ParameterAccessor} * @@ -296,21 +329,7 @@ protected Mono createCountQuery(ConvertingParameterAccessor accessor) { */ protected abstract boolean isLimiting(); - /** - * Obtain a {@link Mono publisher} emitting the {@link SpELExpressionEvaluator} suitable to evaluate expressions - * backed by the given dependencies. - * - * @param dependencies must not be {@literal null}. - * @param accessor must not be {@literal null}. - * @return a {@link Mono} emitting the {@link SpELExpressionEvaluator} when ready. - */ - protected Mono getSpelEvaluatorFor(ExpressionDependencies dependencies, - ConvertingParameterAccessor accessor) { - - return evaluationContextProvider - .getEvaluationContextLater(getQueryMethod().getParameters(), accessor.getValues(), dependencies) - .map(evaluationContext -> (SpELExpressionEvaluator) new DefaultSpELExpressionEvaluator(expressionParser, - evaluationContext)) - .defaultIfEmpty(DefaultSpELExpressionEvaluator.unsupported()); + private static Mono obtainCodecRegistry(MongoDatabase db) { + return Mono.justOrEmpty(db.getCodecRegistry()); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index 6e77b95585..e04e7945aa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.repository.query; import java.time.Duration; -import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -25,17 +24,13 @@ import org.springframework.data.domain.Sort.Order; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; -import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Meta; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.util.json.ParameterBindingContext; -import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -50,10 +45,7 @@ */ abstract class AggregationUtils { - private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); - - private AggregationUtils() { - } + private AggregationUtils() {} /** * Apply a collation extracted from the given {@literal collationExpression} to the given @@ -106,32 +98,6 @@ static AggregationOptions.Builder applyMeta(AggregationOptions.Builder builder, return builder; } - /** - * Compute the {@link AggregationOperation aggregation} pipeline for the given {@link MongoQueryMethod}. The raw - * {@link org.springframework.data.mongodb.repository.Aggregation#pipeline()} is parsed with a - * {@link ParameterBindingDocumentCodec} to obtain the MongoDB native {@link Document} representation returned by - * {@link AggregationOperation#toDocument(AggregationOperationContext)} that is mapped against the domain type - * properties. - * - * @param method - * @param accessor - * @param expressionParser - * @param evaluationContextProvider - * @return - */ - static List computePipeline(MongoQueryMethod method, ConvertingParameterAccessor accessor, - ExpressionParser expressionParser, QueryMethodEvaluationContextProvider evaluationContextProvider) { - - ParameterBindingContext bindingContext = new ParameterBindingContext((accessor::getBindableValue), expressionParser, - () -> evaluationContextProvider.getEvaluationContext(method.getParameters(), accessor.getValues())); - - List target = new ArrayList<>(method.getAnnotatedAggregation().length); - for (String source : method.getAnnotatedAggregation()) { - target.add(ctx -> ctx.getMappedObject(CODEC.decode(source, bindingContext), method.getDomainClass())); - } - return target; - } - /** * Append {@code $sort} aggregation stage if {@link ConvertingParameterAccessor#getSort()} is present. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java index df9608eae6..cacf351d06 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java @@ -49,8 +49,6 @@ */ public class ReactiveStringBasedAggregation extends AbstractReactiveMongoQuery { - private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); - private final ExpressionParser expressionParser; private final ReactiveQueryMethodEvaluationContextProvider evaluationContextProvider; private final ReactiveMongoOperations reactiveMongoOperations; @@ -125,25 +123,29 @@ private boolean isSimpleReturnType(Class targetType) { private Mono> computePipeline(ConvertingParameterAccessor accessor) { - MongoQueryMethod method = getQueryMethod(); - - List> stages = new ArrayList<>(method.getAnnotatedAggregation().length); + return getCodecRegistry().map(ParameterBindingDocumentCodec::new).flatMap(codec -> { - for (String source : method.getAnnotatedAggregation()) { + String[] sourcePipeline = getQueryMethod().getAnnotatedAggregation(); - ExpressionDependencies dependencies = CODEC.captureExpressionDependencies(source, - accessor::getBindableValue, expressionParser); + List> stages = new ArrayList<>(sourcePipeline.length); + for (String source : sourcePipeline) { + stages.add(computePipelineStage(source, accessor, codec)); + } + return Flux.concat(stages).collectList(); + }); + } - Mono stage = getSpelEvaluatorFor(dependencies, accessor).map(it -> { + private Mono computePipelineStage(String source, ConvertingParameterAccessor accessor, + ParameterBindingDocumentCodec codec) { - ParameterBindingContext bindingContext = new ParameterBindingContext(accessor::getBindableValue, it); + ExpressionDependencies dependencies = codec.captureExpressionDependencies(source, accessor::getBindableValue, + expressionParser); - return ctx -> ctx.getMappedObject(CODEC.decode(source, bindingContext), method.getDomainClass()); - }); - stages.add(stage); - } + return getSpelEvaluatorFor(dependencies, accessor).map(it -> { - return Flux.concat(stages).collectList(); + ParameterBindingContext bindingContext = new ParameterBindingContext(accessor::getBindableValue, it); + return ctx -> ctx.getMappedObject(codec.decode(source, bindingContext), getQueryMethod().getDomainClass()); + }); } private AggregationOptions computeOptions(MongoQueryMethod method, ConvertingParameterAccessor accessor) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index 1ab7762d38..43ef9374b2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -44,7 +44,6 @@ public class ReactiveStringBasedMongoQuery extends AbstractReactiveMongoQuery { private static final String COUNT_EXISTS_AND_DELETE = "Manually defined query for %s cannot be a count and exists or delete query at the same time!"; private static final Logger LOG = LoggerFactory.getLogger(ReactiveStringBasedMongoQuery.class); - private static final ParameterBindingDocumentCodec CODEC = new ParameterBindingDocumentCodec(); private final String query; private final String fieldSpec; @@ -121,27 +120,30 @@ public ReactiveStringBasedMongoQuery(String query, ReactiveMongoQueryMethod meth @Override protected Mono createQuery(ConvertingParameterAccessor accessor) { - Mono queryObject = getBindingContext(accessor, expressionParser, this.query) - .map(it -> CODEC.decode(this.query, it)); - Mono fieldsObject = getBindingContext(accessor, expressionParser, this.fieldSpec) - .map(it -> CODEC.decode(this.fieldSpec, it)); + return getCodecRegistry().map(ParameterBindingDocumentCodec::new).flatMap(codec -> { - return queryObject.zipWith(fieldsObject).map(tuple -> { + Mono queryObject = getBindingContext(query, accessor, codec) + .map(context -> codec.decode(query, context)); + Mono fieldsObject = getBindingContext(fieldSpec, accessor, codec) + .map(context -> codec.decode(fieldSpec, context)); - Query query = new BasicQuery(tuple.getT1(), tuple.getT2()).with(accessor.getSort()); + return queryObject.zipWith(fieldsObject).map(tuple -> { - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Created query %s for %s fields.", query.getQueryObject(), query.getFieldsObject())); - } + Query query = new BasicQuery(tuple.getT1(), tuple.getT2()).with(accessor.getSort()); + + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Created query %s for %s fields.", query.getQueryObject(), query.getFieldsObject())); + } - return query; + return query; + }); }); } - private Mono getBindingContext(ConvertingParameterAccessor accessor, - ExpressionParser expressionParser, String json) { + private Mono getBindingContext(String json, ConvertingParameterAccessor accessor, + ParameterBindingDocumentCodec codec) { - ExpressionDependencies dependencies = CODEC.captureExpressionDependencies(json, accessor::getBindableValue, + ExpressionDependencies dependencies = codec.captureExpressionDependencies(json, accessor::getBindableValue, expressionParser); return getSpelEvaluatorFor(dependencies, accessor) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java index 2dea1ff89b..ecbbfa0588 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java @@ -15,11 +15,12 @@ */ package org.springframework.data.mongodb.repository.query; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import org.bson.Document; - +import org.springframework.data.mapping.model.SpELExpressionEvaluator; import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.aggregation.Aggregation; @@ -30,8 +31,11 @@ import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.util.json.ParameterBindingContext; +import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ResultProcessor; +import org.springframework.data.spel.ExpressionDependencies; import org.springframework.expression.ExpressionParser; import org.springframework.util.ClassUtils; @@ -73,7 +77,9 @@ protected Object doExecute(MongoQueryMethod method, ResultProcessor resultProces ConvertingParameterAccessor accessor, Class typeToRead) { if (method.isPageQuery() || method.isSliceQuery()) { - throw new InvalidMongoDbApiUsageException(String.format("Repository aggregation method '%s' does not support '%s' return type. Please use eg. 'List' instead.", method.getName(), method.getReturnType().getType().getSimpleName())); + throw new InvalidMongoDbApiUsageException(String.format( + "Repository aggregation method '%s' does not support '%s' return type. Please use eg. 'List' instead.", + method.getName(), method.getReturnType().getType().getSimpleName())); } Class sourceType = method.getDomainClass(); @@ -125,7 +131,26 @@ private boolean isSimpleReturnType(Class targetType) { } List computePipeline(MongoQueryMethod method, ConvertingParameterAccessor accessor) { - return AggregationUtils.computePipeline(method, accessor, expressionParser, evaluationContextProvider); + + ParameterBindingDocumentCodec codec = new ParameterBindingDocumentCodec(getCodecRegistry()); + String[] sourcePipeline = method.getAnnotatedAggregation(); + + List stages = new ArrayList<>(sourcePipeline.length); + for (String source : sourcePipeline) { + stages.add(computePipelineStage(source, accessor, codec)); + } + return stages; + } + + private AggregationOperation computePipelineStage(String source, ConvertingParameterAccessor accessor, + ParameterBindingDocumentCodec codec) { + + ExpressionDependencies dependencies = codec.captureExpressionDependencies(source, accessor::getBindableValue, + expressionParser); + + SpELExpressionEvaluator evaluator = getSpELExpressionEvaluatorFor(dependencies, accessor); + ParameterBindingContext bindingContext = new ParameterBindingContext(accessor::getBindableValue, evaluator); + return ctx -> ctx.getMappedObject(codec.decode(source, bindingContext), getQueryMethod().getDomainClass()); } private AggregationOptions computeOptions(MongoQueryMethod method, ConvertingParameterAccessor accessor) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index bb6864233c..fb86830f48 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.repository.query; import org.bson.Document; -import org.bson.codecs.configuration.CodecRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.mapping.model.SpELExpressionEvaluator; @@ -31,9 +30,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Assert; -import com.mongodb.MongoClientSettings; -import com.mongodb.client.MongoDatabase; - /** * Query to use a plain JSON String to create the {@link Query} to actually execute. * @@ -50,7 +46,6 @@ public class StringBasedMongoQuery extends AbstractMongoQuery { private final String query; private final String fieldSpec; - private final ParameterBindingDocumentCodec codec; private final ExpressionParser expressionParser; private final QueryMethodEvaluationContextProvider evaluationContextProvider; @@ -112,10 +107,6 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati this.isExistsQuery = false; this.isDeleteQuery = false; } - - CodecRegistry codecRegistry = mongoOperations.execute(MongoDatabase::getCodecRegistry); - this.codec = new ParameterBindingDocumentCodec( - codecRegistry != null ? codecRegistry : MongoClientSettings.getDefaultCodecRegistry()); } /* @@ -125,8 +116,10 @@ public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperati @Override protected Query createQuery(ConvertingParameterAccessor accessor) { - Document queryObject = codec.decode(this.query, getBindingContext(accessor, expressionParser, this.query)); - Document fieldsObject = codec.decode(this.fieldSpec, getBindingContext(accessor, expressionParser, this.fieldSpec)); + ParameterBindingDocumentCodec codec = getParameterBindingCodec(); + + Document queryObject = codec.decode(this.query, getBindingContext(this.query, accessor, codec)); + Document fieldsObject = codec.decode(this.fieldSpec, getBindingContext(this.fieldSpec, accessor, codec)); Query query = new BasicQuery(queryObject, fieldsObject).with(accessor.getSort()); @@ -137,15 +130,13 @@ protected Query createQuery(ConvertingParameterAccessor accessor) { return query; } - private ParameterBindingContext getBindingContext(ConvertingParameterAccessor accessor, - ExpressionParser expressionParser, String json) { + private ParameterBindingContext getBindingContext(String json, ConvertingParameterAccessor accessor, + ParameterBindingDocumentCodec codec) { ExpressionDependencies dependencies = codec.captureExpressionDependencies(json, accessor::getBindableValue, expressionParser); - SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(expressionParser, evaluationContextProvider - .getEvaluationContext(getQueryMethod().getParameters(), accessor.getValues(), dependencies)); - + SpELExpressionEvaluator evaluator = getSpELExpressionEvaluatorFor(dependencies, accessor); return new ParameterBindingContext(accessor::getBindableValue, evaluator); } @@ -189,4 +180,8 @@ private static boolean hasAmbiguousProjectionFlags(boolean isCountQuery, boolean boolean isDeleteQuery) { return BooleanUtil.countBooleanTrueValues(isCountQuery, isExistsQuery, isDeleteQuery) > 1; } + + private ParameterBindingDocumentCodec getParameterBindingCodec() { + return new ParameterBindingDocumentCodec(getCodecRegistry()); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java index 35fb113cbd..f7c255bed1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregationUnitTests.java @@ -91,6 +91,7 @@ public void setUp() { converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); when(operations.getConverter()).thenReturn(converter); when(operations.aggregate(any(TypedAggregation.class), any())).thenReturn(Flux.empty()); + when(operations.execute(any())).thenReturn(Flux.empty()); } @Test // DATAMONGO-2153 @@ -166,6 +167,13 @@ public void aggregateWithCollationParameter() { assertThat(collationOf(invocation)).isEqualTo(Collation.of("en_US")); } + @Test // DATAMONGO-2557 + void aggregationRetrievesCodecFromDriverJustOnceForMultipleAggregationOperationsInPipeline() { + + executeAggregation("multiOperationPipeline", "firstname"); + verify(operations).execute(any()); + } + private AggregationInvocation executeAggregation(String name, Object... args) { Class[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(size -> new Class[size]); @@ -228,6 +236,9 @@ private interface SampleRepository extends ReactiveCrudRepository @Aggregation(GROUP_BY_LASTNAME_STRING_WITH_SPEL_PARAMETER_PLACEHOLDER) Mono spelParameterReplacementAggregation(String arg0); + @Aggregation(pipeline = {RAW_GROUP_BY_LASTNAME_STRING, GROUP_BY_LASTNAME_STRING_WITH_SPEL_PARAMETER_PLACEHOLDER}) + Mono multiOperationPipeline(String arg0); + @Aggregation(pipeline = RAW_GROUP_BY_LASTNAME_STRING, collation = "de_AT") Mono aggregateWithCollation(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java index 19f1ae4851..1fd5f68e05 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQueryUnitTests.java @@ -19,6 +19,8 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -62,6 +64,7 @@ * @author Christoph Strobl */ @ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class ReactiveStringBasedMongoQueryUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -76,6 +79,7 @@ public class ReactiveStringBasedMongoQueryUnitTests { public void setUp() { when(operations.query(any())).thenReturn(reactiveFind); + when(operations.execute(any())).thenReturn(Flux.empty()); this.converter = new MappingMongoConverter(factory, new MongoMappingContext()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java index c24701deab..9c2d828cfe 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedAggregationUnitTests.java @@ -66,6 +66,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; +import com.mongodb.MongoClientSettings; + /** * Unit tests for {@link StringBasedAggregation}. * @@ -97,6 +99,7 @@ public void setUp() { converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); when(operations.getConverter()).thenReturn(converter); when(operations.aggregate(any(TypedAggregation.class), any())).thenReturn(aggregationResults); + when(operations.execute(any())).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); } @Test // DATAMONGO-2153 @@ -218,6 +221,13 @@ public void aggregateRaisesErrorOnInvalidReturnType() { .withMessageContaining("Page"); } + @Test // DATAMONGO-2557 + void aggregationRetrievesCodecFromDriverJustOnceForMultipleAggregationOperationsInPipeline() { + + executeAggregation("multiOperationPipeline", "firstname"); + verify(operations).execute(any()); + } + private AggregationInvocation executeAggregation(String name, Object... args) { Class[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new); @@ -291,6 +301,9 @@ private interface SampleRepository extends Repository { @Aggregation(GROUP_BY_LASTNAME_STRING_WITH_SPEL_PARAMETER_PLACEHOLDER) PersonAggregate spelParameterReplacementAggregation(String arg0); + @Aggregation(pipeline = { RAW_GROUP_BY_LASTNAME_STRING, GROUP_BY_LASTNAME_STRING_WITH_SPEL_PARAMETER_PLACEHOLDER }) + PersonAggregate multiOperationPipeline(String arg0); + @Aggregation(pipeline = RAW_GROUP_BY_LASTNAME_STRING, collation = "de_AT") PersonAggregate aggregateWithCollation(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 30b32cb915..9366d5e4a4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -39,6 +39,8 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.springframework.data.mongodb.core.DbCallback; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; @@ -72,6 +74,7 @@ * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public class StringBasedMongoQueryUnitTests { SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -88,6 +91,7 @@ public void setUp() { this.converter = new MappingMongoConverter(factory, new MongoMappingContext()); doReturn(findOperation).when(operations).query(any()); + doReturn(MongoClientSettings.getDefaultCodecRegistry()).when(operations).execute(any()); } @Test From a44a0034b7faab6921eef6877b6d77f0ddaa4cac Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 27 Jul 2020 09:01:47 +0200 Subject: [PATCH 0228/1381] DATAMONGO-2557 - Polishing. Inline methods. Original pull request: #879. --- .../data/mongodb/repository/query/AbstractMongoQuery.java | 6 +----- .../repository/query/AbstractReactiveMongoQuery.java | 8 ++------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java index e74e7d64ba..376ba31b9e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java @@ -234,7 +234,7 @@ protected SpELExpressionEvaluator getSpELExpressionEvaluatorFor(ExpressionDepend * @since 2.4 */ protected CodecRegistry getCodecRegistry() { - return operations.execute(AbstractMongoQuery::obtainCodecRegistry); + return operations.execute(MongoDatabase::getCodecRegistry); } /** @@ -275,8 +275,4 @@ protected CodecRegistry getCodecRegistry() { * @since 2.0.4 */ protected abstract boolean isLimiting(); - - private static CodecRegistry obtainCodecRegistry(MongoDatabase db) { - return db.getCodecRegistry(); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index aba7a46c2b..c451cfce7f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -20,6 +20,7 @@ import org.bson.Document; import org.bson.codecs.configuration.CodecRegistry; import org.reactivestreams.Publisher; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mapping.model.SpELExpressionEvaluator; @@ -44,7 +45,6 @@ import org.springframework.util.Assert; import com.mongodb.MongoClientSettings; -import com.mongodb.reactivestreams.client.MongoDatabase; /** * Base class for reactive {@link RepositoryQuery} implementations for MongoDB. @@ -286,7 +286,7 @@ protected Mono getSpelEvaluatorFor(ExpressionDependenci */ protected Mono getCodecRegistry() { - return Mono.from(operations.execute(AbstractReactiveMongoQuery::obtainCodecRegistry)) + return Mono.from(operations.execute(db -> Mono.just(db.getCodecRegistry()))) .defaultIfEmpty(MongoClientSettings.getDefaultCodecRegistry()); } @@ -328,8 +328,4 @@ protected Mono getCodecRegistry() { * @since 2.0.4 */ protected abstract boolean isLimiting(); - - private static Mono obtainCodecRegistry(MongoDatabase db) { - return Mono.justOrEmpty(db.getCodecRegistry()); - } } From 6a43f28466eabeb9a3c70adac04a6caed7fdaadb Mon Sep 17 00:00:00 2001 From: Jay Bryant Date: Thu, 25 Jun 2020 14:56:11 -0500 Subject: [PATCH 0229/1381] DATAMONGO-2598 - Wording changes. Removed the language of oppression and violence and replaced it with more neutral language. Note that problematic words in the code have to remain in the docs until the code changes. Original pull request: #872. --- src/main/asciidoc/new-features.adoc | 2 +- .../asciidoc/reference/change-streams.adoc | 4 +- .../client-session-transactions.adoc | 8 +-- src/main/asciidoc/reference/jmx.adoc | 2 +- src/main/asciidoc/reference/mapping.adoc | 3 +- .../mongo-repositories-aggregation.adoc | 2 +- src/main/asciidoc/reference/mongodb.adoc | 58 +++++++++---------- .../asciidoc/reference/query-by-example.adoc | 2 +- .../reactive-mongo-repositories.adoc | 2 +- .../asciidoc/reference/reactive-mongodb.adoc | 14 ++--- .../asciidoc/reference/tailable-cursors.adoc | 4 +- 11 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index c773caa890..f833753829 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -44,7 +44,7 @@ [[new-features.2-1-0]] == What's New in Spring Data MongoDB 2.1 -* Cursor-based aggregation execution. +* Cursor-based aggregation. * <> for imperative and reactive Template APIs. * Support for Map/Reduce through the reactive Template API. * <>. diff --git a/src/main/asciidoc/reference/change-streams.adoc b/src/main/asciidoc/reference/change-streams.adoc index 0461370703..02843a9599 100644 --- a/src/main/asciidoc/reference/change-streams.adoc +++ b/src/main/asciidoc/reference/change-streams.adoc @@ -16,7 +16,7 @@ In doubt, use `Document`. Listening to a https://docs.mongodb.com/manual/tutorial/change-streams-example/[Change Stream by using a Sync Driver] creates a long running, blocking task that needs to be delegated to a separate component. In this case, we need to first create a `MessageListenerContainer`, which will be the main entry point for running the specific `SubscriptionRequest` tasks. -Spring Data MongoDB already ships with a default implementation that operates on `MongoTemplate` and is capable of creating and executing `Task` instances for a `ChangeStreamRequest`. +Spring Data MongoDB already ships with a default implementation that operates on `MongoTemplate` and is capable of creating and running `Task` instances for a `ChangeStreamRequest`. The following example shows how to use Change Streams with `MessageListener` instances: @@ -39,7 +39,7 @@ container.stop(); <1> Starting the container initializes the resources and starts `Task` instances for already registered `SubscriptionRequest` instances. Requests added after startup are ran immediately. <2> Define the listener called when a `Message` is received. The `Message#getBody()` is converted to the requested domain type. Use `Document` to receive raw results without conversion. <3> Set the collection to listen to and provide additional options through `ChangeStreamOptions`. -<4> Register the request. The returned `Subscription` can be used to check the current `Task` state and cancel its execution to free resources. +<4> Register the request. The returned `Subscription` can be used to check the current `Task` state and cancel it to free resources. <5> Do not forget to stop the container once you are sure you no longer need it. Doing so stops all running `Task` instances within the container. ==== diff --git a/src/main/asciidoc/reference/client-session-transactions.adoc b/src/main/asciidoc/reference/client-session-transactions.adoc index 490ae8d195..22eaa7a80b 100644 --- a/src/main/asciidoc/reference/client-session-transactions.adoc +++ b/src/main/asciidoc/reference/client-session-transactions.adoc @@ -221,7 +221,7 @@ NOTE: `@Transactional(readOnly = true)` advises `MongoTransactionManager` to als == Reactive Transactions Same as with the reactive `ClientSession` support, the `ReactiveMongoTemplate` offers dedicated methods for operating -within a transaction without having to worry about the commit/abort actions depending on the operations outcome. +within a transaction without having to worry about the committing or stopping actions depending on the operations outcome. NOTE: Unless you specify a `ReactiveMongoTransactionManager` within your application context, transaction support is *DISABLED*. You can use `setSessionSynchronization(ALWAYS)` to participate in ongoing non-native MongoDB transactions. @@ -249,7 +249,7 @@ Mono result = Mono <1> First we obviously need to initiate the session. <2> Once we have the `ClientSession` at hand, start the transaction. <3> Operate within the transaction by passing on the `ClientSession` to the operation. -<4> If the operations completes exceptionally, we need to abort the transaction and preserve the error. +<4> If the operations completes exceptionally, we need to stop the transaction and preserve the error. <5> Or of course, commit the changes in case of success. Still preserving the operations result. <6> Lastly, we need to make sure to close the session. ==== @@ -339,7 +339,7 @@ Inside transactions, MongoDB server has a slightly different behavior. *Connection Settings* The MongoDB drivers offer a dedicated replica set name configuration option turing the driver into auto detection -mode. This option helps identifying replica set master nodes and command routing during a transaction. +mode. This option helps identifying replica set manager nodes and command routing during a transaction. NOTE: Make sure to add `replicaSet` to the MongoDB URI. Please refer to https://docs.mongodb.com/manual/reference/connection-string/#connections-connection-options[connection string options] for further details. @@ -351,7 +351,7 @@ structures in place. *Transient Errors* -MongoDB can add special labels to errors raised during transactional execution. Those may indicate transient failures +MongoDB can add special labels to errors raised during transactional operations. Those may indicate transient failures that might vanish by merely retrying the operation. We highly recommend https://github.com/spring-projects/spring-retry[Spring Retry] for those purposes. Nevertheless one may override `MongoTransactionManager#doCommit(MongoTransactionObject)` to implement a https://docs.mongodb.com/manual/core/transactions/#retry-commit-operation[Retry Commit Operation] diff --git a/src/main/asciidoc/reference/jmx.adoc b/src/main/asciidoc/reference/jmx.adoc index 27f40a9095..287ebd4a46 100644 --- a/src/main/asciidoc/reference/jmx.adoc +++ b/src/main/asciidoc/reference/jmx.adoc @@ -1,7 +1,7 @@ [[mongo.jmx]] = JMX support -The JMX support for MongoDB exposes the results of executing the 'serverStatus' command on the admin database for a single MongoDB server instance. It also exposes an administrative MBean, `MongoAdmin`, that lets you perform administrative operations, such as dropping or creating a database. The JMX features build upon the JMX feature set available in the Spring Framework. See https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/integration.html#jmx[here] for more details. +The JMX support for MongoDB exposes the results of running the 'serverStatus' command on the admin database for a single MongoDB server instance. It also exposes an administrative MBean, `MongoAdmin`, that lets you perform administrative operations, such as dropping or creating a database. The JMX features build upon the JMX feature set available in the Spring Framework. See https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/integration.html#jmx[here] for more details. [[mongodb:jmx-configuration]] == MongoDB JMX Configuration diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index b2977883d5..d6bf5b2b5d 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -548,6 +548,7 @@ public class Person { } // other getters/setters omitted +} ---- [TIP] @@ -784,7 +785,7 @@ class Nested { [[mapping-usage-references]] === Using DBRefs -The mapping framework does not have to store child objects embedded within the document. You can also store them separately and use a DBRef to refer to that document. When the object is loaded from MongoDB, those references are eagerly resolved so that you get back a mapped object that looks the same as if it had been stored embedded within your master document. +The mapping framework does not have to store child objects embedded within the document. You can also store them separately and use a DBRef to refer to that document. When the object is loaded from MongoDB, those references are eagerly resolved so that you get back a mapped object that looks the same as if it had been stored embedded within your controlling document. The following example uses a DBRef to refer to a specific document that exists independently of the object in which it is referenced (both classes are shown in-line for brevity's sake): diff --git a/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc b/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc index 2372aaedec..8fe1b13dee 100644 --- a/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc +++ b/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc @@ -73,7 +73,7 @@ To gain more control, you might consider `AggregationResult` as method return ty <8> Like in <6>, a single value can be directly obtained from multiple result ``Document``s. ==== -In some scenarios aggregations might require additional options like a maximum execution time, additional log comments or the permission to temporarily write data to disk. +In some scenarios, aggregations might require additional options, such as a maximum run time, additional log comments, or the permission to temporarily write data to disk. Use the `@Meta` annotation to set those options via `maxExecutionTimeMs`, `comment` or `allowDiskUse`. [source,java] diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 9e076d6e3e..75ad097ce9 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -417,7 +417,7 @@ The default converter implementation used by `MongoTemplate` is `MappingMongoCon Another central feature of `MongoTemplate` is translation of exceptions thrown by the MongoDB Java driver into Spring's portable Data Access Exception hierarchy. See "`<>`" for more information. -`MongoTemplate` offers many convenience methods to help you easily perform common tasks. However, if you need to directly access the MongoDB driver API, you can use one of several `Execute` callback methods. The execute callbacks gives you a reference to either a `com.mongodb.client.MongoCollection` or a `com.mongodb.client.MongoDatabase` object. See the <> section for more information. +`MongoTemplate` offers many convenience methods to help you easily perform common tasks. However, if you need to directly access the MongoDB driver API, you can use one of several `Execute` callback methods. The `execute` callbacks gives you a reference to either a `com.mongodb.client.MongoCollection` or a `com.mongodb.client.MongoDatabase` object. See the <> section for more information. The next section contains an example of how to work with the `MongoTemplate` in the context of the Spring container. @@ -875,7 +875,7 @@ In addition to the `Query` discussed earlier, we provide the update definition b Most methods return the `Update` object to provide a fluent style for the API. [[mongodb-template-update.methods]] -==== Methods for Executing Updates for Documents +==== Methods for Running Updates for Documents * *updateFirst*: Updates the first document that matches the query document criteria with the updated document. * *updateMulti*: Updates all objects that match the query document criteria with the updated document. @@ -1054,7 +1054,7 @@ db.students.update( <3> ---- <1> The 1st `$set` stage calculates a new field _average_ based on the average of the _tests_ field. <2> The 2nd `$set` stage calculates a new field _grade_ based on the _average_ field calculated by the first aggregation stage. -<3> The pipeline is executed on the _students_ collection and uses `Student` for the aggregation field mapping. +<3> The pipeline is run on the _students_ collection and uses `Student` for the aggregation field mapping. <4> Apply the update to all matching documents in the collection. ==== @@ -1080,7 +1080,7 @@ Optional result = template.update(Person.class) <1> <2> The actual match query mapped against the given domain type. Provide `sort`, `fields` and `collation` settings via the query. <3> Additional optional hook to provide options other than the defaults, like `upsert`. <4> An optional projection type used for mapping the operation result. If none given the initial domain type is used. -<5> Trigger the actual execution. Use `findAndReplaceValue` to obtain the nullable result instead of an `Optional`. +<5> Trigger the actual processing. Use `findAndReplaceValue` to obtain the nullable result instead of an `Optional`. ==== IMPORTANT: Please note that the replacement must not hold an `id` itself as the `id` of the existing `Document` will be @@ -1107,7 +1107,7 @@ template.findAllAndRemove(new Query().limit(3), "GOT"); <5> ---- <1> Remove a single entity specified by its `_id` from the associated collection. <2> Remove all documents that match the criteria of the query from the `GOT` collection. -<3> Remove the first three documents in the `GOT` collection. Unlike <2>, the documents to remove are identified by their `_id`, executing the given query, applying `sort`, `limit`, and `skip` options first, and then removing all at once in a separate step. +<3> Remove the first three documents in the `GOT` collection. Unlike <2>, the documents to remove are identified by their `_id`, running the given query, applying `sort`, `limit`, and `skip` options first, and then removing all at once in a separate step. <4> Remove all documents matching the criteria of the query from the `GOT` collection. Unlike <3>, documents do not get deleted in a batch but one by one. <5> Remove the first three documents in the `GOT` collection. Unlike <3>, documents do not get deleted in a batch but one by one. ==== @@ -1521,7 +1521,7 @@ repo.findByLocationWithin( <4> new Polygon( new Point(-73.992514, 40.758934), new Point(-73.961138, 40.760348), - new Point(-73.991658, 40.730006)); + new Point(-73.991658, 40.730006))); ---- <1> Repository method definition using the commons type allows calling it with both the GeoJSON and the legacy format. <2> Use GeoJSON type to make use of `$geometry` operator. @@ -1724,7 +1724,7 @@ db.foo.createIndex( ) ---- -A query searching for `coffee cake` can be defined and executed as follows: +A query searching for `coffee cake` can be defined and run as follows: .Full Text Query ==== @@ -1808,7 +1808,7 @@ collation is applied to index creation and queries unless you specify a differen whole operation and cannot be specified on a per-field basis. Like other metadata, collations can be be derived from the domain type via the `collation` attribute of the `@Document` -annotation and will be applied directly when executing queries, creating collections or indexes. +annotation and will be applied directly when running queries, creating collections or indexes. NOTE: Annotated collations will not be used when a collection is auto created by MongoDB on first interaction. This would require additional store interaction delaying the entire process. Please use `MongoOperations.createCollection` for those cases. @@ -2125,7 +2125,7 @@ target type is a closed interface or DTO projection. You can switch between retrieving a single entity and retrieving multiple entities as a `List` or a `Stream` through the terminating methods: `first()`, `one()`, `all()`, or `stream()`. -When writing a geo-spatial query with `near(NearQuery)`, the number of terminating methods is altered to include only the methods that are valid for executing a `geoNear` command in MongoDB (fetching entities as a `GeoResult` within `GeoResults`), as the following example shows: +When writing a geo-spatial query with `near(NearQuery)`, the number of terminating methods is altered to include only the methods that are valid for running a `geoNear` command in MongoDB (fetching entities as a `GeoResult` within `GeoResults`), as the following example shows: ==== [source,java] @@ -2224,7 +2224,7 @@ As of Spring Data MongoDB 3.x any `count` operation uses regardless the existenc [NOTE] ==== -MongoDBs native `countDocuments` method, and the executed `$match` aggregation, does not support `$near` and `$nearSphere` but require `$geoWithin` along with `$center` or `$centerSphere` which does not support `$minDistance` (see https://jira.mongodb.org/browse/SERVER-37043). +MongoDBs native `countDocuments` method and the `$match` aggregation, do not support `$near` and `$nearSphere` but require `$geoWithin` along with `$center` or `$centerSphere` which does not support `$minDistance` (see https://jira.mongodb.org/browse/SERVER-37043). Therefore a given `Query` will be rewritten for `count` operations using `Reactive`-/`MongoTemplate` to bypass the issue like shown below. @@ -2247,7 +2247,7 @@ Therefore a given `Query` will be rewritten for `count` operations using `Reacti You can query MongoDB by using Map-Reduce, which is useful for batch processing, for data aggregation, and for when the query language does not fulfill your needs. -Spring provides integration with MongoDB's Map-Reduce by providing methods on `MongoOperations` to simplify the creation and execution of Map-Reduce operations.It can convert the results of a Map-Reduce operation to a POJO and integrates with Spring's https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#resources[Resource abstraction].This lets you place your JavaScript files on the file system, classpath, HTTP server, or any other Spring Resource implementation and then reference the JavaScript resources through an easy URI style syntax -- for example, `classpath:reduce.js;`.Externalizing JavaScript code in files is often preferable to embedding them as Java strings in your code.Note that you can still pass JavaScript code as Java strings if you prefer. +Spring provides integration with MongoDB's Map-Reduce by providing methods on `MongoOperations` to simplify the creation and running of Map-Reduce operations.It can convert the results of a Map-Reduce operation to a POJO and integrates with Spring's https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#resources[Resource abstraction].This lets you place your JavaScript files on the file system, classpath, HTTP server, or any other Spring Resource implementation and then reference the JavaScript resources through an easy URI style syntax -- for example, `classpath:reduce.js;`.Externalizing JavaScript code in files is often preferable to embedding them as Java strings in your code.Note that you can still pass JavaScript code as Java strings if you prefer. [[mongo.mapreduce.example]] === Example Usage @@ -2379,7 +2379,7 @@ by `ScriptOperations`. + There is no replacement for the removed functionality. ==== -MongoDB allows executing JavaScript functions on the server by either directly sending the script or calling a stored one. `ScriptOperations` can be accessed through `MongoTemplate` and provides basic abstraction for `JavaScript` usage. The following example shows how to us the `ScriptOperations` class: +MongoDB allows running JavaScript functions on the server by either directly sending the script or calling a stored one. `ScriptOperations` can be accessed through `MongoTemplate` and provides basic abstraction for `JavaScript` usage. The following example shows how to us the `ScriptOperations` class: ==== [source,java] @@ -2392,9 +2392,9 @@ scriptOps.execute(echoScript, "directly execute script"); <1> scriptOps.register(new NamedMongoScript("echo", echoScript)); <2> scriptOps.call("echo", "execute script via name"); <3> ---- -<1> Execute the script directly without storing the function on server side. +<1> Run the script directly without storing the function on server side. <2> Store the script using 'echo' as its name. The given name identifies the script and allows calling it later. -<3> Execute the script with name 'echo' using the provided parameters. +<3> Run the script with name 'echo' using the provided parameters. ==== [[mongo.group]] @@ -2402,7 +2402,7 @@ scriptOps.call("echo", "execute script via name"); <3> As an alternative to using Map-Reduce to perform data aggregation, you can use the https://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group[`group` operation] which feels similar to using SQL's group by query style, so it may feel more approachable vs. using Map-Reduce. Using the group operations does have some limitations, for example it is not supported in a shared environment and it returns the full result set in a single BSON object, so the result should be small, less than 10,000 keys. -Spring provides integration with MongoDB's group operation by providing methods on MongoOperations to simplify the creation and execution of group operations. It can convert the results of the group operation to a POJO and also integrates with Spring's https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#resources[Resource abstraction] abstraction. This will let you place your JavaScript files on the file system, classpath, http server or any other Spring Resource implementation and then reference the JavaScript resources via an easy URI style syntax, e.g. 'classpath:reduce.js;. Externalizing JavaScript code in files if often preferable to embedding them as Java strings in your code. Note that you can still pass JavaScript code as Java strings if you prefer. +Spring provides integration with MongoDB's group operation by providing methods on MongoOperations to simplify the creation and running of group operations. It can convert the results of the group operation to a POJO and also integrates with Spring's https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#resources[Resource abstraction] abstraction. This will let you place your JavaScript files on the file system, classpath, http server or any other Spring Resource implementation and then reference the JavaScript resources via an easy URI style syntax, e.g. 'classpath:reduce.js;. Externalizing JavaScript code in files if often preferable to embedding them as Java strings in your code. Note that you can still pass JavaScript code as Java strings if you prefer. [[mongo.group.example]] === Example Usage @@ -2419,7 +2419,7 @@ In order to understand how group operations work the following example is used, { "_id" : ObjectId("4ec1d25d41421e2015da64f6"), "x" : 3 } ---- -We would like to group by the only field in each row, the `x` field and aggregate the number of times each specific value of `x` occurs. To do this we need to create an initial document that contains our count variable and also a reduce function which will increment it each time it is encountered. The Java code to execute the group operation is shown below +We would like to group by the only field in each row, the `x` field and aggregate the number of times each specific value of `x` occurs. To do this we need to create an initial document that contains our count variable and also a reduce function which will increment it each time it is encountered. The Java code to run the group operation is shown below [source,java] ---- @@ -2508,13 +2508,13 @@ The Aggregation Framework support in Spring Data MongoDB is based on the followi + An `Aggregation` represents a MongoDB `aggregate` operation and holds the description of the aggregation pipeline instructions. Aggregations are created by invoking the appropriate `newAggregation(…)` static factory method of the `Aggregation` class, which takes a list of `AggregateOperation` and an optional input class. + -The actual aggregate operation is executed by the `aggregate` method of the `MongoTemplate`, which takes the desired output class as a parameter. +The actual aggregate operation is run by the `aggregate` method of the `MongoTemplate`, which takes the desired output class as a parameter. + * `TypedAggregation` + A `TypedAggregation`, just like an `Aggregation`, holds the instructions of the aggregation pipeline and a reference to the input type, that is used for mapping domain properties to actual document fields. + -On execution field references get checked against the given input type considering potential `@Field` annotations and raising errors when referencing non existing properties. +At runtime, field references get checked against the given input type, considering potential `@Field` annotations and raising errors when referencing nonexistent properties. + * `AggregationOperation` + @@ -2755,7 +2755,7 @@ A sort by count operation is equivalent to the following BSON (Binary JSON): [[mongo.aggregation.projection.expressions]] ==== Spring Expression Support in Projection Expressions -We support the use of SpEL expressions in projection expressions through the `andExpression` method of the `ProjectionOperation` and `BucketOperation` classes. This feature lets you define the desired expression as a SpEL expression. On query execution, the SpEL expression is translated into a corresponding MongoDB projection expression part. This arrangement makes it much easier to express complex calculations. +We support the use of SpEL expressions in projection expressions through the `andExpression` method of the `ProjectionOperation` and `BucketOperation` classes. This feature lets you define the desired expression as a SpEL expression. On running a query, the SpEL expression is translated into a corresponding MongoDB projection expression part. This arrangement makes it much easier to express complex calculations. ===== Complex Calculations with SpEL expressions @@ -3226,16 +3226,16 @@ mongoTemplate.dropCollection("MyNewCollection"); NOTE: Collection creation allows customization with `CollectionOptions` and supports <>. [[mongo-template.commands]] -== Executing Commands +== Running Commands You can get at the MongoDB driver's `MongoDatabase.runCommand( )` method by using the `executeCommand(…)` methods on `MongoTemplate`. These methods also perform exception translation into Spring's `DataAccessException` hierarchy. [[mongo-template.commands.execution]] -=== Methods for executing commands +=== Methods for running commands * `Document` *executeCommand* `(Document command)`: Run a MongoDB command. * `Document` *executeCommand* `(Document command, ReadPreference readPreference)`: Run a MongoDB command with the given nullable MongoDB `ReadPreference`. -* `Document` *executeCommand* `(String jsonCommand)`: Execute a MongoDB command expressed as a JSON string. +* `Document` *executeCommand* `(String jsonCommand)`: Run a MongoDB command expressed as a JSON string. [[mongodb.mapping-usage.events]] == Lifecycle Events @@ -3299,19 +3299,19 @@ Some of the mappings performed by the `MongoExceptionTranslator` are `com.mongod [[mongo.executioncallback]] == Execution Callbacks -One common design feature of all Spring template classes is that all functionality is routed into one of the template's execute callback methods. Doing so helps to ensure that exceptions and any resource management that may be required are performed consistently. While JDBC and JMS need this feature much more than MongoDB does, it still offers a single spot for exception translation and logging to occur. Consequently, using these execute callbacks is the preferred way to access the MongoDB driver's `MongoDatabase` and `MongoCollection` objects to perform uncommon operations that were not exposed as methods on `MongoTemplate`. +One common design feature of all Spring template classes is that all functionality is routed into one of the template's `execute` callback methods. Doing so helps to ensure that exceptions and any resource management that may be required are performed consistently. While JDBC and JMS need this feature much more than MongoDB does, it still offers a single spot for exception translation and logging to occur. Consequently, using these `execute` callbacks is the preferred way to access the MongoDB driver's `MongoDatabase` and `MongoCollection` objects to perform uncommon operations that were not exposed as methods on `MongoTemplate`. -The following list describes the execute callback methods. +The following list describes the `execute` callback methods. -* ` T` *execute* `(Class entityClass, CollectionCallback action)`: Executes the given `CollectionCallback` for the entity collection of the specified class. +* ` T` *execute* `(Class entityClass, CollectionCallback action)`: Runs the given `CollectionCallback` for the entity collection of the specified class. -* ` T` *execute* `(String collectionName, CollectionCallback action)`: Executes the given `CollectionCallback` on the collection of the given name. +* ` T` *execute* `(String collectionName, CollectionCallback action)`: Runs the given `CollectionCallback` on the collection of the given name. -* ` T` *execute* `(DbCallback action)`: Executes a DbCallback translating any exceptions as necessary. Spring Data MongoDB provides support for the Aggregation Framework introduced to MongoDB in version 2.2. +* ` T` *execute* `(DbCallback action)`: Runs a DbCallback, translating any exceptions as necessary. Spring Data MongoDB provides support for the Aggregation Framework introduced to MongoDB in version 2.2. -* ` T` *execute* `(String collectionName, DbCallback action)`: Executes a `DbCallback` on the collection of the given name translating any exceptions as necessary. +* ` T` *execute* `(String collectionName, DbCallback action)`: Runs a `DbCallback` on the collection of the given name translating any exceptions as necessary. -* ` T` *executeInSession* `(DbCallback action)`: Executes the given `DbCallback` within the same connection to the database so as to ensure consistency in a write-heavy environment where you may read the data that you wrote. +* ` T` *executeInSession* `(DbCallback action)`: Runs the given `DbCallback` within the same connection to the database so as to ensure consistency in a write-heavy environment where you may read the data that you wrote. The following example uses the `CollectionCallback` to return information about an index: diff --git a/src/main/asciidoc/reference/query-by-example.adoc b/src/main/asciidoc/reference/query-by-example.adoc index 59b8d20021..d1f5ce5aaf 100644 --- a/src/main/asciidoc/reference/query-by-example.adoc +++ b/src/main/asciidoc/reference/query-by-example.adoc @@ -1,4 +1,4 @@ -[[query-by-example.execution]] +[[query-by-example.running]] == Running an Example The following example shows how to query by example when using a repository (of `Person` objects, in this case): diff --git a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc index e0aea3b00b..b58a6ff6e7 100644 --- a/src/main/asciidoc/reference/reactive-mongo-repositories.adoc +++ b/src/main/asciidoc/reference/reactive-mongo-repositories.adoc @@ -235,7 +235,7 @@ It provides the following features: See the http://www.querydsl.com/static/querydsl/latest/reference/html/[Querydsl documentation] for how to bootstrap your environment for APT-based code generation using Maven or Ant. -The Querydsl repository support lets you write and execute queries such as the following: +The Querydsl repository support lets you write and run queries, such as the following: [source,java] ---- diff --git a/src/main/asciidoc/reference/reactive-mongodb.adoc b/src/main/asciidoc/reference/reactive-mongodb.adoc index ec4eb581e3..4298e50f67 100644 --- a/src/main/asciidoc/reference/reactive-mongodb.adoc +++ b/src/main/asciidoc/reference/reactive-mongodb.adoc @@ -19,7 +19,7 @@ For most tasks, you should use `ReactiveMongoTemplate` or the repository support Spring MongoDB support requires MongoDB 2.6 or higher and Java SE 8 or higher. -First, you need to set up a running MongoDB server. Refer to the https://docs.mongodb.org/manual/core/introduction/[MongoDB Quick Start guide] for an explanation on how to startup a MongoDB instance. Once installed, starting MongoDB is typically a matter of executing the following command: `${MONGO_HOME}/bin/mongod` +First, you need to set up a running MongoDB server. Refer to the https://docs.mongodb.org/manual/core/introduction/[MongoDB Quick Start guide] for an explanation on how to startup a MongoDB instance. Once installed, starting MongoDB is typically a matter of running the following command: `${MONGO_HOME}/bin/mongod` To create a Spring project in STS, go to File -> New -> Spring Template Project -> Simple Spring Utility Project and press Yes when prompted. Then enter a project and a package name, such as org.spring.mongodb.example. @@ -462,15 +462,15 @@ NOTE: The preceding example is meant to show the use of save, update, and remove [[mongo.reactive.executioncallback]] == Execution Callbacks -One common design feature of all Spring template classes is that all functionality is routed into one of the templates execute callback methods. This helps ensure that exceptions and any resource management that maybe required are performed consistency. While this was of much greater need in the case of JDBC and JMS than with MongoDB, it still offers a single spot for exception translation and logging to occur. As such, using the execute callback is the preferred way to access the MongoDB driver's `MongoDatabase` and `MongoCollection` objects to perform uncommon operations that were not exposed as methods on `ReactiveMongoTemplate`. +One common design feature of all Spring template classes is that all functionality is routed into one of the templates that run callback methods. This helps ensure that exceptions and any resource management that maybe required are performed consistency. While this was of much greater need in the case of JDBC and JMS than with MongoDB, it still offers a single spot for exception translation and logging to occur. As such, using the `execute` callback is the preferred way to access the MongoDB driver's `MongoDatabase` and `MongoCollection` objects to perform uncommon operations that were not exposed as methods on `ReactiveMongoTemplate`. -Here is a list of execute callback methods. +Here is a list of `execute` callback methods. -* ` Flux` *execute* `(Class entityClass, ReactiveCollectionCallback action)`: Executes the given `ReactiveCollectionCallback` for the entity collection of the specified class. +* ` Flux` *execute* `(Class entityClass, ReactiveCollectionCallback action)`: Runs the given `ReactiveCollectionCallback` for the entity collection of the specified class. -* ` Flux` *execute* `(String collectionName, ReactiveCollectionCallback action)`: Executes the given `ReactiveCollectionCallback` on the collection of the given name. +* ` Flux` *execute* `(String collectionName, ReactiveCollectionCallback action)`: Runs the given `ReactiveCollectionCallback` on the collection of the given name. -* ` Flux` *execute* `(ReactiveDatabaseCallback action)`: Executes a `ReactiveDatabaseCallback` translating any exceptions as necessary. +* ` Flux` *execute* `(ReactiveDatabaseCallback action)`: Runs a `ReactiveDatabaseCallback` translating any exceptions as necessary. The following example uses the `ReactiveCollectionCallback` to return information about an index: @@ -556,7 +556,7 @@ class ReactiveGridFsClient { NOTE: Currently, MongoDB does not support defining sort criteria when retrieving files from GridFS. For this reason, any sort criteria defined on the `Query` instance handed into the `find(…)` method are disregarded. The other option to read files from the GridFs is to use the methods modeled along the lines of `ResourcePatternResolver`. -`ReactiveGridFsOperations` uses reactive types to defer execution while `ResourcePatternResolver` uses a synchronous interface. +`ReactiveGridFsOperations` uses reactive types to defer running while `ResourcePatternResolver` uses a synchronous interface. These methods allow handing an Ant path into the method and can thus retrieve files matching the given pattern. The following example shows how to use `ReactiveGridFsTemplate` to read files: .Using ReactiveGridFsTemplate to read files diff --git a/src/main/asciidoc/reference/tailable-cursors.adoc b/src/main/asciidoc/reference/tailable-cursors.adoc index b6233df909..09a8950f91 100644 --- a/src/main/asciidoc/reference/tailable-cursors.adoc +++ b/src/main/asciidoc/reference/tailable-cursors.adoc @@ -19,7 +19,7 @@ concept that is already prevalent in the Spring ecosystem. Listening to a capped collection using a Sync Driver creates a long running, blocking task that needs to be delegated to a separate component. In this case, we need to first create a `MessageListenerContainer`, which will be the main entry point for running the specific `SubscriptionRequest`. Spring Data MongoDB already ships with a default implementation that -operates on `MongoTemplate` and is capable of creating and executing `Task` instances for a `TailableCursorRequest`. +operates on `MongoTemplate` and is capable of creating and running `Task` instances for a `TailableCursorRequest`. The following example shows how to use tailable cursors with `MessageListener` instances: @@ -49,7 +49,7 @@ container.stop(); <3> Set the collection to listen to. <4> Provide an optional filter for documents to receive. <5> Set the message listener to publish incoming ``Message``s to. -<6> Register the request. The returned `Subscription` can be used to check the current `Task` state and cancel its execution to free resources. +<6> Register the request. The returned `Subscription` can be used to check the current `Task` state and cancel it to free resources. <5> Do not forget to stop the container once you are sure you no longer need it. Doing so stops all running `Task` instances within the container. ==== From 2ea3ceda2db4e062b9ffa097883b90a39f400592 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Jul 2020 15:20:49 +0200 Subject: [PATCH 0230/1381] DATAMONGO-2598 - Polishing. Original pull request: #872. --- src/main/asciidoc/reference/client-session-transactions.adoc | 2 +- src/main/asciidoc/reference/mapping.adoc | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/asciidoc/reference/client-session-transactions.adoc b/src/main/asciidoc/reference/client-session-transactions.adoc index 22eaa7a80b..0067cc9b40 100644 --- a/src/main/asciidoc/reference/client-session-transactions.adoc +++ b/src/main/asciidoc/reference/client-session-transactions.adoc @@ -339,7 +339,7 @@ Inside transactions, MongoDB server has a slightly different behavior. *Connection Settings* The MongoDB drivers offer a dedicated replica set name configuration option turing the driver into auto detection -mode. This option helps identifying replica set manager nodes and command routing during a transaction. +mode. This option helps identifying the primary replica set nodes and command routing during a transaction. NOTE: Make sure to add `replicaSet` to the MongoDB URI. Please refer to https://docs.mongodb.com/manual/reference/connection-string/#connections-connection-options[connection string options] for further details. diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index d6bf5b2b5d..98ecf074d5 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -785,7 +785,9 @@ class Nested { [[mapping-usage-references]] === Using DBRefs -The mapping framework does not have to store child objects embedded within the document. You can also store them separately and use a DBRef to refer to that document. When the object is loaded from MongoDB, those references are eagerly resolved so that you get back a mapped object that looks the same as if it had been stored embedded within your controlling document. +The mapping framework does not have to store child objects embedded within the document. +You can also store them separately and use a DBRef to refer to that document. +When the object is loaded from MongoDB, those references are eagerly resolved so that you get back a mapped object that looks the same as if it had been stored embedded within your top-level document. The following example uses a DBRef to refer to a specific document that exists independently of the object in which it is referenced (both classes are shown in-line for brevity's sake): From 8e84d397e2a69d3aa48ac5e348ec6f9e39d95e7c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Jul 2020 15:40:26 +0200 Subject: [PATCH 0231/1381] DATAMONGO-2564 - Fix link to code of conduct. --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index a6b69f9747..f875e3dddf 100644 --- a/README.adoc +++ b/README.adoc @@ -10,7 +10,7 @@ Key functional areas of Spring Data MongoDB are a POJO centric model for interac == Code of Conduct -This project is governed by the link:CODE_OF_CONDUCT.adoc[Spring Code of Conduct]. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io. +This project is governed by the https://github.com/spring-projects/.github/blob/e3cc2ff230d8f1dca06535aa6b5a4a23815861d4/CODE_OF_CONDUCT.md[Spring Code of Conduct]. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io. == Getting Started From 95c9789f43fc04f537c56a97e94f0329850fc5be Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 30 Jul 2020 16:19:10 +0200 Subject: [PATCH 0232/1381] DATAMONGO-2599 - Eagerly consider enum types as simple types. MongoSimpleTypes now eagerly checks if a type is a simple one to avoid PersistentEntity registration for ChronoUnit. --- .../mongodb/core/mapping/MongoSimpleTypes.java | 5 +++++ .../mapping/MongoMappingContextUnitTests.java | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java index 21cee062ec..4a999ce08b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java @@ -48,6 +48,7 @@ * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ public abstract class MongoSimpleTypes { @@ -109,6 +110,10 @@ public abstract class MongoSimpleTypes { @Override public boolean isSimpleType(Class type) { + if (type.isEnum()) { + return true; + } + if (type.getName().startsWith("java.time")) { return false; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java index d922edd951..4262c5448f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.*; +import java.time.temporal.ChronoUnit; import java.util.AbstractMap; import java.util.Collections; import java.util.Locale; @@ -160,6 +161,18 @@ void shouldRejectClassWithInvalidTextScoreProperty() { .withMessageContaining("score").withMessageContaining("Float").withMessageContaining("Double"); } + @Test // DATAMONGO-2599 + void shouldNotCreateEntityForEnum() { + + MongoMappingContext context = new MongoMappingContext(); + + BasicMongoPersistentEntity entity = context.getRequiredPersistentEntity(ClassWithChronoUnit.class); + + assertThat(entity.getPersistentProperty("unit").isEntity()).isFalse(); + assertThat(context.hasPersistentEntityFor(ChronoUnit.class)).isFalse(); + assertThat(context.getPersistentEntity(ChronoUnit.class)).isNull(); + } + public class SampleClass { Map children; @@ -226,4 +239,9 @@ class ClassWithInvalidTextScoreProperty { @TextScore Locale score; } + + class ClassWithChronoUnit { + + ChronoUnit unit; + } } From b1f5717d63a13760393fa30a372fe9743935ec51 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 31 Jul 2020 11:11:41 +0200 Subject: [PATCH 0233/1381] DATAMONGO-2601 - Suppress results for suspended query methods returning kotlin.Unit. We now discard results for suspended query methods if the return type is kotlin.Unit. Related ticket: DATACMNS-1779 --- .../query/ReactiveMongoQueryExecution.java | 7 +- .../CoroutineRepositoryUnitTests.kt | 68 +++++++++++++++++++ .../repository/KotlinRepositoryUnitTests.kt | 61 +++++++++++++++++ 3 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/CoroutineRepositoryUnitTests.kt create mode 100644 spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/KotlinRepositoryUnitTests.kt diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 2ca038ba89..66fe7c8492 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -32,6 +32,7 @@ import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.repository.query.ReturnedType; import org.springframework.data.repository.util.ReactiveWrappers; +import org.springframework.data.util.ReflectionUtils; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -203,7 +204,7 @@ public Object convert(Object source) { ReturnedType returnedType = processor.getReturnedType(); - if (isVoid(returnedType)) { + if (ReflectionUtils.isVoid(returnedType.getReturnedType())) { if (source instanceof Mono) { return ((Mono) source).then(); @@ -228,8 +229,4 @@ public Object convert(Object source) { return processor.processResult(source, converter); } } - - static boolean isVoid(ReturnedType returnedType) { - return returnedType.getReturnedType().equals(Void.class); - } } diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/CoroutineRepositoryUnitTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/CoroutineRepositoryUnitTests.kt new file mode 100644 index 0000000000..3d49709b88 --- /dev/null +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/CoroutineRepositoryUnitTests.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2020 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 + * + * https://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.repository + +import com.mongodb.client.result.DeleteResult +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.data.annotation.Id +import org.springframework.data.mongodb.core.ReactiveMongoOperations +import org.springframework.data.mongodb.core.convert.MappingMongoConverter +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver +import org.springframework.data.mongodb.core.mapping.MongoMappingContext +import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactory +import org.springframework.data.repository.kotlin.CoroutineCrudRepository +import reactor.core.publisher.Mono + +/** + * Unit tests for Kotlin Coroutine repositories. + * + * @author Mark Paluch + */ +class CoroutineRepositoryUnitTests { + + val operations = mockk(relaxed = true) + lateinit var repositoryFactory: ReactiveMongoRepositoryFactory + + @BeforeEach + fun before() { + + every { operations.getConverter() } returns MappingMongoConverter(NoOpDbRefResolver.INSTANCE, MongoMappingContext()) + repositoryFactory = ReactiveMongoRepositoryFactory(operations) + } + + @Test // DATAMONGO-2601 + fun `should discard result of suspended query method without result`() { + + every { operations.remove(any(), any(), any()) } returns Mono.just(DeleteResult.acknowledged(1)) + + val repository = repositoryFactory.getRepository(PersonRepository::class.java) + + runBlocking { + repository.deleteAllByName("foo") + } + } + + interface PersonRepository : CoroutineCrudRepository { + + suspend fun deleteAllByName(name: String) + } + + data class Person(@Id var id: Long, var name: String) +} diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/KotlinRepositoryUnitTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/KotlinRepositoryUnitTests.kt new file mode 100644 index 0000000000..de8fb9255f --- /dev/null +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/KotlinRepositoryUnitTests.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2020 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 + * + * https://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.repository + +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.data.annotation.Id +import org.springframework.data.mongodb.core.MongoOperations +import org.springframework.data.mongodb.core.convert.MappingMongoConverter +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver +import org.springframework.data.mongodb.core.mapping.MongoMappingContext +import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory +import org.springframework.data.repository.CrudRepository + +/** + * Unit tests for Kotlin repositories. + * + * @author Mark Paluch + */ +class KotlinRepositoryUnitTests { + + val operations = mockk(relaxed = true) + lateinit var repositoryFactory: MongoRepositoryFactory + + @BeforeEach + fun before() { + + every { operations.getConverter() } returns MappingMongoConverter(NoOpDbRefResolver.INSTANCE, MongoMappingContext()) + repositoryFactory = MongoRepositoryFactory(operations) + } + + @Test // DATAMONGO-2601 + fun should() { + + val repository = repositoryFactory.getRepository(PersonRepository::class.java) + + repository.deleteAllByName("foo") + } + + interface PersonRepository : CrudRepository { + + fun deleteAllByName(name: String) + } + + data class Person(@Id var id: Long, var name: String) +} From 707ad8e2322e38ac325ff19b8bdbc8c0dd6a5b9a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 31 Jul 2020 11:24:42 +0200 Subject: [PATCH 0234/1381] DATAMONGO-1894 - Polishing. Preinitialize EvaluationContextProvider with ReactiveQueryMethodEvaluationContextProvider to not require setting properties on vanilla ReactiveMongoRepositoryFactory objects. --- .../repository/support/ReactiveMongoRepositoryFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java index f55f6ed8fc..aac577e3de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java @@ -75,6 +75,7 @@ public ReactiveMongoRepositoryFactory(ReactiveMongoOperations mongoOperations) { this.operations = mongoOperations; this.mappingContext = mongoOperations.getConverter().getMappingContext(); + setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT); } /* From c6f12ef0e27fafefee95d4e273e0f2ecfb4cb36f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 3 Aug 2020 17:14:24 +0200 Subject: [PATCH 0235/1381] DATAMONGO-2602 - Upgrade MongoDB drivers to 4.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 98fb76d5c0..9d352e7658 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.4.0-SNAPSHOT - 4.1.0-rc0 + 4.1.0 ${mongo} 1.19 From bfab233d2f04341de2faa7552d92f4cf773d4211 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 4 Aug 2020 13:34:50 +0200 Subject: [PATCH 0236/1381] DATAMONGO-2603 - Adopt to Reactor 3.4 changes. Align with ContextView and changes in other operators. --- .../mongodb/core/ReactiveMongoContext.java | 20 ++++++++++++++----- .../mongodb/core/ReactiveMongoTemplate.java | 2 +- .../mongodb/test/util/MongoTestUtils.java | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java index 007cdeb7b5..8cd27a2bbd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java @@ -15,11 +15,15 @@ */ package org.springframework.data.mongodb.core; -import org.reactivestreams.Publisher; -import org.springframework.util.Assert; import reactor.core.publisher.Mono; import reactor.util.context.Context; +import java.util.function.Function; + +import org.reactivestreams.Publisher; + +import org.springframework.util.Assert; + import com.mongodb.reactivestreams.client.ClientSession; /** @@ -29,7 +33,7 @@ * @author Christoph Strobl * @author Mark Paluch * @since 2.1 - * @see Mono#subscriberContext() + * @see Mono#deferContextual(Function) * @see Context */ public class ReactiveMongoContext { @@ -46,8 +50,14 @@ public class ReactiveMongoContext { */ public static Mono getSession() { - return Mono.subscriberContext().filter(ctx -> ctx.hasKey(SESSION_KEY)) - .flatMap(ctx -> ctx.> get(SESSION_KEY)); + return Mono.deferContextual(ctx -> { + + if (ctx.hasKey(SESSION_KEY)) { + return ctx.> get(SESSION_KEY); + } + + return Mono.empty(); + }); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index da60cd671c..7b35ea1f42 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -572,7 +572,7 @@ private Flux withSession(ReactiveSessionCallback action, ClientSession ReactiveMongoTemplate.this); return Flux.from(action.doInSession(operations)) // - .subscriberContext(ctx -> ReactiveMongoContext.setSession(ctx, Mono.just(session))); + .contextWrite(ctx -> ReactiveMongoContext.setSession(ctx, Mono.just(session))); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 1e0e34261b..46708e2805 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -35,6 +35,7 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.reactivestreams.client.MongoClients; +import reactor.util.retry.Retry; /** * Utility to create (and reuse) imperative and reactive {@code MongoClient} instances. @@ -160,7 +161,7 @@ public static void dropCollectionNow(String dbName, String collectionName, .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); Mono.from(database.getCollection(collectionName).drop()) // - .delayElement(getTimeout()).retryBackoff(3, Duration.ofMillis(250)) // + .delayElement(getTimeout()).retryWhen(Retry.backoff(3, Duration.ofMillis(250))) // .as(StepVerifier::create) // .verifyComplete(); } From 6e47d5c76edc6f315d4e12d7cbefebf52d7958de Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 4 Aug 2020 13:35:12 +0200 Subject: [PATCH 0237/1381] DATAMONGO-2603 - Polishing. Add missing Deprecated annotation. --- .../org/springframework/data/mongodb/core/query/BasicUpdate.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java index 00d148b890..9d1693f210 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java @@ -67,6 +67,7 @@ public Update push(String key, @Nullable Object value) { } @Override + @Deprecated public Update pushAll(String key, Object[] values) { Document keyValue = new Document(); keyValue.put(key, values); From 22bd3e64be408831853ee2edb49d994873e5ebb8 Mon Sep 17 00:00:00 2001 From: Yadhukrishna S Pai Date: Sun, 19 Jul 2020 15:50:58 +0530 Subject: [PATCH 0238/1381] DATAMONGO-1836 - Add support to hint in aggregation options. Original pull request: #878. --- .../data/mongodb/core/MongoTemplate.java | 5 ++ .../mongodb/core/ReactiveMongoTemplate.java | 3 ++ .../core/aggregation/AggregationOptions.java | 49 +++++++++++++++++-- .../mongodb/core/MongoTemplateUnitTests.java | 12 +++++ .../core/ReactiveMongoTemplateUnitTests.java | 12 +++++ .../aggregation/AggregationOptionsTests.java | 20 ++++++-- 6 files changed, 93 insertions(+), 8 deletions(-) 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 acdcfd7a98..fba9171fe4 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 @@ -155,6 +155,7 @@ * @author Cimon Lucas * @author Michael J. Simons * @author Roman Puchkovskiy + * @author Yadhukrishna S Pai */ public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider { @@ -2149,6 +2150,8 @@ protected AggregationResults doAggregate(Aggregation aggregation, String options.getComment().ifPresent(aggregateIterable::comment); + options.getHint().ifPresent(aggregateIterable::hint); + if (options.hasExecutionTimeLimit()) { aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS); } @@ -2207,6 +2210,8 @@ protected CloseableIterator aggregateStream(Aggregation aggregation, Stri options.getComment().ifPresent(cursor::comment); + options.getHint().ifPresent(cursor::hint); + Class domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() : null; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 7b35ea1f42..c7ee5cc87e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -146,6 +146,7 @@ * @author Christoph Strobl * @author Roman Puchkovskiy * @author Mathieu Ouellet + * @author Yadhukrishna S Pai * @since 2.0 */ public class ReactiveMongoTemplate implements ReactiveMongoOperations, ApplicationContextAware { @@ -1024,6 +1025,8 @@ private Flux aggregateAndMap(MongoCollection collection, List operations.forType(inputType).getCollation()) // .map(Collation::toMongoCollation) // .ifPresent(cursor::collation); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index fc59282156..520f3b18f5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -32,6 +32,7 @@ * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch + * @author Yadhukrishna S Pai * @see Aggregation#withOptions(AggregationOptions) * @see TypedAggregation#withOptions(AggregationOptions) * @since 1.6 @@ -45,12 +46,14 @@ public class AggregationOptions { private static final String COLLATION = "collation"; private static final String COMMENT = "comment"; private static final String MAX_TIME = "maxTimeMS"; + private static final String HINT = "hint"; private final boolean allowDiskUse; private final boolean explain; private final Optional cursor; private final Optional collation; private final Optional comment; + private final Optional hint; private Duration maxTime = Duration.ZERO; private ResultOptions resultOptions = ResultOptions.READ; @@ -77,7 +80,7 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, Document cursor */ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor, @Nullable Collation collation) { - this(allowDiskUse, explain, cursor, collation, null); + this(allowDiskUse, explain, cursor, collation, null, null); } /** @@ -89,16 +92,18 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Docum * aggregation. * @param collation collation for string comparison. Can be {@literal null}. * @param comment execution comment. Can be {@literal null}. + * @param hint can be {@literal null}, used to provide an index that would be forcibly used by query optimizer. * @since 2.2 */ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor, - @Nullable Collation collation, @Nullable String comment) { + @Nullable Collation collation, @Nullable String comment, @Nullable Document hint) { this.allowDiskUse = allowDiskUse; this.explain = explain; this.cursor = Optional.ofNullable(cursor); this.collation = Optional.ofNullable(collation); this.comment = Optional.ofNullable(comment); + this.hint = Optional.ofNullable(hint); } /** @@ -130,8 +135,9 @@ public static AggregationOptions fromDocument(Document document) { Collation collation = document.containsKey(COLLATION) ? Collation.from(document.get(COLLATION, Document.class)) : null; String comment = document.getString(COMMENT); + Document hint = document.get(HINT, Document.class); - AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment); + AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment, hint); if (document.containsKey(MAX_TIME)) { options.maxTime = Duration.ofMillis(document.getLong(MAX_TIME)); } @@ -212,6 +218,16 @@ public Optional getComment() { return comment; } + /** + * Get the hint used to to fulfill the aggregation. + * + * @return never {@literal null}. + */ + public Optional getHint() { + return hint; + } + + /** * @return the time limit for processing. {@link Duration#ZERO} is used for the default unbounded behavior. * @since 3.0 @@ -248,6 +264,10 @@ Document applyAndReturnPotentiallyChangedCommand(Document command) { result.put(EXPLAIN, explain); } + if (result.containsKey(HINT)) { + hint.ifPresent(val -> result.append(HINT, val)); + } + if (!result.containsKey(CURSOR)) { cursor.ifPresent(val -> result.put(CURSOR, val)); } @@ -277,6 +297,7 @@ public Document toDocument() { cursor.ifPresent(val -> document.put(CURSOR, val)); collation.ifPresent(val -> document.append(COLLATION, val.toDocument())); comment.ifPresent(val -> document.append(COMMENT, val)); + hint.ifPresent(val -> document.append(HINT, val)); if (hasExecutionTimeLimit()) { document.append(MAX_TIME, maxTime.toMillis()); @@ -318,6 +339,7 @@ public static class Builder { private @Nullable Document cursor; private @Nullable Collation collation; private @Nullable String comment; + private @Nullable Document hint; private @Nullable Duration maxTime; private @Nullable ResultOptions resultOptions; @@ -396,6 +418,19 @@ public Builder comment(@Nullable String comment) { return this; } + /** + * Define a hint is used forcibly by query optimizer to to fulfill the aggregation. + * + * @param hint can be {@literal null}. + * @return this. + * @since 2.2 + */ + public Builder hint(@Nullable Document hint) { + + this.hint = hint; + return this; + } + /** * Set the time limit for processing. * @@ -431,7 +466,13 @@ public Builder skipOutput() { */ public AggregationOptions build() { - AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment); + AggregationOptions options = new AggregationOptions( + allowDiskUse, + explain, + cursor, + collation, + comment, + hint); if (maxTime != null) { options.maxTime = maxTime; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index e0484e225b..30f666ed40 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -139,6 +139,7 @@ * @author Mark Paluch * @author Michael J. Simons * @author Roman Puchkovskiy + * @author Yadhukrishna S Pai */ @MockitoSettings(strictness = Strictness.LENIENT) public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @@ -468,6 +469,17 @@ void aggregateShouldHonorOptionsComment() { verify(aggregateIterable).comment("expensive"); } + @Test // DATAMONGO-1836 + void aggregateShouldHonorOptionsHint() { + + Document hint = new Document("dummyField", 1); + AggregationOptions options = AggregationOptions.builder().hint(hint).build(); + + template.aggregate(newAggregation(Aggregation.unwind("foo")).withOptions(options), "collection-1", Wrapper.class); + + verify(aggregateIterable).hint(hint); + } + @Test // DATAMONGO-1166, DATAMONGO-2264 void geoNearShouldHonorReadPreferenceWhenSet() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index bd310e872d..65041210e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -117,6 +117,7 @@ * @author Christoph Strobl * @author Roman Puchkovskiy * @author Mathieu Ouellet + * @author Yadhukrishna S Pai */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -628,6 +629,17 @@ void aggregateShouldHonorOptionsComment() { verify(aggregatePublisher).comment("expensive"); } + @Test // DATAMONGO-1836 + void aggregateShouldHonorOptionsHint() { + Document hint = new Document("dummyHint", 1); + AggregationOptions options = AggregationOptions.builder().hint(hint).build(); + + template.aggregate(newAggregation(Sith.class, project("id")).withOptions(options), AutogenerateableId.class, + Document.class).subscribe(); + + verify(aggregatePublisher).hint(hint); + } + @Test // DATAMONGO-2390 void aggregateShouldNoApplyZeroOrNegativeMaxTime() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java index 1e46b48362..0bb41022fc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java @@ -28,10 +28,12 @@ * @author Thomas Darimont * @author Mark Paluch * @author Christoph Strobl + * @author Yadhukrishna S Pai * @since 1.6 */ public class AggregationOptionsTests { + private final Document dummyHint = new Document("dummyField", 1); AggregationOptions aggregationOptions; @BeforeEach @@ -40,18 +42,20 @@ public void setup() { .cursorBatchSize(1) // .allowDiskUse(true) // .comment("hola!") // + .hint(dummyHint) // .build(); } - @Test // DATAMONGO-960 + @Test // DATAMONGO-960, DATAMONGO-1836 public void aggregationOptionsBuilderShouldSetOptionsAccordingly() { assertThat(aggregationOptions.isAllowDiskUse()).isTrue(); assertThat(aggregationOptions.isExplain()).isTrue(); assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1)); + assertThat(aggregationOptions.getHint().get()).isEqualTo(dummyHint); } - @Test // DATAMONGO-1637, DATAMONGO-2153 + @Test // DATAMONGO-1637, DATAMONGO-2153, DATAMONGO-1836 public void shouldInitializeFromDocument() { Document document = new Document(); @@ -59,6 +63,7 @@ public void shouldInitializeFromDocument() { document.put("explain", true); document.put("allowDiskUse", true); document.put("comment", "hola!"); + document.put("hint", dummyHint); aggregationOptions = AggregationOptions.fromDocument(document); @@ -67,12 +72,19 @@ public void shouldInitializeFromDocument() { assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1)); assertThat(aggregationOptions.getCursorBatchSize()).isEqualTo(1); assertThat(aggregationOptions.getComment().get()).isEqualTo("hola!"); + assertThat(aggregationOptions.getHint().get()).isEqualTo(dummyHint); } - @Test // DATAMONGO-960, DATAMONGO-2153 + @Test // DATAMONGO-960, DATAMONGO-2153, DATAMONGO-1836 public void aggregationOptionsToString() { assertThat(aggregationOptions.toDocument()).isEqualTo(Document.parse( - "{ \"allowDiskUse\" : true , \"explain\" : true , \"cursor\" : { \"batchSize\" : 1}, \"comment\": \"hola!\"}")); + "{ " + + "\"allowDiskUse\" : true , " + + "\"explain\" : true , " + + "\"cursor\" : { \"batchSize\" : 1}, " + + "\"comment\": \"hola!\", " + + "\"hint\" : { \"dummyField\" : 1}" + + "}")); } } From 5795a507bde1551ffdc03057a59549e65426a92b Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 6 Aug 2020 11:25:26 +0200 Subject: [PATCH 0239/1381] DATAMONGO-1836 - Polishing. Revert constructor change of AggregationOptions to not break existing code. Update since tags. Reformat code. Align visibility of AggregationOptionsTests with JUnit 5 rules. Update documentation. Original pull request: #878. --- .../data/mongodb/core/MongoTemplate.java | 2 - .../mongodb/core/ReactiveMongoTemplate.java | 1 - .../core/aggregation/AggregationOptions.java | 38 ++++++++++++------- .../core/ReactiveMongoTemplateUnitTests.java | 1 + .../aggregation/AggregationOptionsTests.java | 31 +++++++-------- src/main/asciidoc/new-features.adoc | 1 + 6 files changed, 39 insertions(+), 35 deletions(-) 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 fba9171fe4..97deaae467 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 @@ -2149,7 +2149,6 @@ protected AggregationResults doAggregate(Aggregation aggregation, String } options.getComment().ifPresent(aggregateIterable::comment); - options.getHint().ifPresent(aggregateIterable::hint); if (options.hasExecutionTimeLimit()) { @@ -2209,7 +2208,6 @@ protected CloseableIterator aggregateStream(Aggregation aggregation, Stri } options.getComment().ifPresent(cursor::comment); - options.getHint().ifPresent(cursor::hint); Class domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index c7ee5cc87e..64fe99f08a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -1024,7 +1024,6 @@ private Flux aggregateAndMap(MongoCollection collection, List operations.forType(inputType).getCollation()) // diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 520f3b18f5..2c500149da 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -74,7 +74,7 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, Document cursor * @param allowDiskUse whether to off-load intensive sort-operations to disk. * @param explain whether to get the execution plan for the aggregation instead of the actual results. * @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the - * aggregation. + * aggregation. * @param collation collation for string comparison. Can be {@literal null}. * @since 2.0 */ @@ -89,13 +89,29 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Docum * @param allowDiskUse whether to off-load intensive sort-operations to disk. * @param explain whether to get the execution plan for the aggregation instead of the actual results. * @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the - * aggregation. + * aggregation. * @param collation collation for string comparison. Can be {@literal null}. * @param comment execution comment. Can be {@literal null}. - * @param hint can be {@literal null}, used to provide an index that would be forcibly used by query optimizer. * @since 2.2 */ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor, + @Nullable Collation collation, @Nullable String comment) { + this(allowDiskUse, explain, cursor, collation, comment, null); + } + + /** + * Creates a new {@link AggregationOptions}. + * + * @param allowDiskUse whether to off-load intensive sort-operations to disk. + * @param explain whether to get the execution plan for the aggregation instead of the actual results. + * @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the + * aggregation. + * @param collation collation for string comparison. Can be {@literal null}. + * @param comment execution comment. Can be {@literal null}. + * @param hint can be {@literal null}, used to provide an index that would be forcibly used by query optimizer. + * @since 3.1 + */ + private AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor, @Nullable Collation collation, @Nullable String comment, @Nullable Document hint) { this.allowDiskUse = allowDiskUse; @@ -222,12 +238,12 @@ public Optional getComment() { * Get the hint used to to fulfill the aggregation. * * @return never {@literal null}. + * @since 3.1 */ public Optional getHint() { return hint; } - /** * @return the time limit for processing. {@link Duration#ZERO} is used for the default unbounded behavior. * @since 3.0 @@ -419,11 +435,11 @@ public Builder comment(@Nullable String comment) { } /** - * Define a hint is used forcibly by query optimizer to to fulfill the aggregation. + * Define a hint that is used by query optimizer to to fulfill the aggregation. * * @param hint can be {@literal null}. * @return this. - * @since 2.2 + * @since 3.1 */ public Builder hint(@Nullable Document hint) { @@ -435,7 +451,7 @@ public Builder hint(@Nullable Document hint) { * Set the time limit for processing. * * @param maxTime {@link Duration#ZERO} is used for the default unbounded behavior. {@link Duration#isNegative() - * Negative} values will be ignored. + * Negative} values will be ignored. * @return this. * @since 3.0 */ @@ -466,13 +482,7 @@ public Builder skipOutput() { */ public AggregationOptions build() { - AggregationOptions options = new AggregationOptions( - allowDiskUse, - explain, - cursor, - collation, - comment, - hint); + AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment, hint); if (maxTime != null) { options.maxTime = maxTime; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 65041210e7..916123d70b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -631,6 +631,7 @@ void aggregateShouldHonorOptionsComment() { @Test // DATAMONGO-1836 void aggregateShouldHonorOptionsHint() { + Document hint = new Document("dummyHint", 1); AggregationOptions options = AggregationOptions.builder().hint(hint).build(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java index 0bb41022fc..15e0af58a5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java @@ -31,13 +31,13 @@ * @author Yadhukrishna S Pai * @since 1.6 */ -public class AggregationOptionsTests { +class AggregationOptionsTests { private final Document dummyHint = new Document("dummyField", 1); AggregationOptions aggregationOptions; @BeforeEach - public void setup() { + void setup() { aggregationOptions = newAggregationOptions().explain(true) // .cursorBatchSize(1) // .allowDiskUse(true) // @@ -47,16 +47,16 @@ public void setup() { } @Test // DATAMONGO-960, DATAMONGO-1836 - public void aggregationOptionsBuilderShouldSetOptionsAccordingly() { + void aggregationOptionsBuilderShouldSetOptionsAccordingly() { assertThat(aggregationOptions.isAllowDiskUse()).isTrue(); assertThat(aggregationOptions.isExplain()).isTrue(); - assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1)); - assertThat(aggregationOptions.getHint().get()).isEqualTo(dummyHint); + assertThat(aggregationOptions.getCursor()).contains(new Document("batchSize", 1)); + assertThat(aggregationOptions.getHint()).contains(dummyHint); } @Test // DATAMONGO-1637, DATAMONGO-2153, DATAMONGO-1836 - public void shouldInitializeFromDocument() { + void shouldInitializeFromDocument() { Document document = new Document(); document.put("cursor", new Document("batchSize", 1)); @@ -69,22 +69,17 @@ public void shouldInitializeFromDocument() { assertThat(aggregationOptions.isAllowDiskUse()).isTrue(); assertThat(aggregationOptions.isExplain()).isTrue(); - assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1)); + assertThat(aggregationOptions.getCursor()).contains(new Document("batchSize", 1)); assertThat(aggregationOptions.getCursorBatchSize()).isEqualTo(1); - assertThat(aggregationOptions.getComment().get()).isEqualTo("hola!"); - assertThat(aggregationOptions.getHint().get()).isEqualTo(dummyHint); + assertThat(aggregationOptions.getComment()).contains("hola!"); + assertThat(aggregationOptions.getHint()).contains(dummyHint); } @Test // DATAMONGO-960, DATAMONGO-2153, DATAMONGO-1836 - public void aggregationOptionsToString() { + void aggregationOptionsToString() { - assertThat(aggregationOptions.toDocument()).isEqualTo(Document.parse( - "{ " + - "\"allowDiskUse\" : true , " + - "\"explain\" : true , " + - "\"cursor\" : { \"batchSize\" : 1}, " + - "\"comment\": \"hola!\", " + - "\"hint\" : { \"dummyField\" : 1}" + - "}")); + assertThat(aggregationOptions.toDocument()).isEqualTo(Document + .parse("{ " + "\"allowDiskUse\" : true , " + "\"explain\" : true , " + "\"cursor\" : { \"batchSize\" : 1}, " + + "\"comment\": \"hola!\", " + "\"hint\" : { \"dummyField\" : 1}" + "}")); } } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index f833753829..7727e28391 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -6,6 +6,7 @@ * <> enabled through `@EnableReactiveMongoAuditing`. `@EnableMongoAuditing` no longer registers `ReactiveAuditingEntityCallback`. * Reactive SpEL support in `@Query` and `@Aggregation` query methods. +* Aggregation hints via `AggregationOptions.builder().hint(bson).build()`. [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 From a7e3ed2e370322673530837ce65043161faaf73e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Aug 2020 11:51:28 +0200 Subject: [PATCH 0240/1381] DATAMONGO-2579 - Updated changelog. --- src/main/resources/changelog.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 4d660632dd..5c24c16a72 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,23 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.0-M2 (2020-08-12) +---------------------------------------- +* DATAMONGO-2603 - Adopt to Reactor 3.4 changes. +* DATAMONGO-2602 - Upgrade MongoDB drivers to 4.1.0. +* DATAMONGO-2601 - Consider Unit a void type in Coroutine repositories. +* DATAMONGO-2599 - Ambiguous field mapping detected for enum java.time.temporal.ChronoUnit. +* DATAMONGO-2598 - Wording changes. +* DATAMONGO-2591 - Upgrade MongoDB drivers to 4.1.0-rc0. +* DATAMONGO-2586 - Add support for reactive auditing. +* DATAMONGO-2579 - Release 3.1 M2 (2020.0.0). +* DATAMONGO-2571 - regex expression included "/" character can't be parsed in the stage of aggregation annotation. +* DATAMONGO-2536 - Add option to discard results on $out and $merge. +* DATAMONGO-2490 - @DBRef fetched without ClientSession when using Spring Transactions. +* DATAMONGO-1894 - Use reactive subscriber context for SpEL evaluation in query execution. +* DATAMONGO-1836 - Add support for hint option to aggregation. + + Changes in version 3.0.2.RELEASE (2020-07-22) --------------------------------------------- * DATAMONGO-2589 - Upgrade to MongoDB Driver 4.0.5. @@ -3112,5 +3129,6 @@ Repository + From fd25f39236df59eab9132200a66c13c2a0eddfea Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Aug 2020 11:51:40 +0200 Subject: [PATCH 0241/1381] DATAMONGO-2579 - Prepare 3.1 M2 (2020.0.0). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9d352e7658..eddb0323c9 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-SNAPSHOT + 2.4.0-M2 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-SNAPSHOT + 2.4.0-M2 4.1.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index ca04e4475c..39953ea2f9 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.1 M1 (2020.0.0) +Spring Data MongoDB 3.1 M2 (2020.0.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -16,3 +16,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 450365992a6dbdd3cddaf4946ff451dd7be6b338 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Aug 2020 11:52:05 +0200 Subject: [PATCH 0242/1381] DATAMONGO-2579 - Release version 3.1 M2 (2020.0.0). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index eddb0323c9..220b34acf0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M2 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a85b081e26..4527b37ad6 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M2 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 33014c7c4f..7757899190 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M2 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ea401d5618..ab581d487b 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-M2 ../pom.xml From 88b1f9fcb361bd4adb6e44f7392663cbc2f59f05 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Aug 2020 12:00:19 +0200 Subject: [PATCH 0243/1381] DATAMONGO-2579 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 220b34acf0..eddb0323c9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M2 + 3.1.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 4527b37ad6..a85b081e26 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M2 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 7757899190..33014c7c4f 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M2 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ab581d487b..ea401d5618 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-M2 + 3.1.0-SNAPSHOT ../pom.xml From 542de64711213a245c4b89c2977c6bd46adb3849 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Aug 2020 12:00:22 +0200 Subject: [PATCH 0244/1381] DATAMONGO-2579 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index eddb0323c9..9d352e7658 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-M2 + 2.4.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-M2 + 2.4.0-SNAPSHOT 4.1.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 90aa7b8f8905dad7e667606ec20ecdb0b1cc72a3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 12 Aug 2020 13:07:08 +0200 Subject: [PATCH 0245/1381] DATAMONGO-2594 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 5c24c16a72..d86f167834 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.3.RELEASE (2020-08-12) +--------------------------------------------- +* DATAMONGO-2601 - Consider Unit a void type in Coroutine repositories. +* DATAMONGO-2599 - Ambiguous field mapping detected for enum java.time.temporal.ChronoUnit. +* DATAMONGO-2598 - Wording changes. +* DATAMONGO-2594 - Release 3.0.3 (Neumann SR3). + + Changes in version 3.1.0-M2 (2020-08-12) ---------------------------------------- * DATAMONGO-2603 - Adopt to Reactor 3.4 changes. @@ -3130,5 +3138,6 @@ Repository + From b388659c3fa9cd0b85a38937c130a6a611734d06 Mon Sep 17 00:00:00 2001 From: Michal Kurcius Date: Wed, 19 Aug 2020 23:08:00 +0200 Subject: [PATCH 0246/1381] DATAMONGO-2613 - Fix single element ArrayJsonSchemaObject to document mapping. Now toDocument calls toDocument on items correctly. Original Pull Request: #883 --- .../data/mongodb/core/schema/TypedJsonSchemaObject.java | 3 ++- .../mongodb/core/schema/JsonSchemaObjectUnitTests.java | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java index a481c53c7a..48e9540ecd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java @@ -41,6 +41,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Michał Kurcius * @since 2.1 */ public class TypedJsonSchemaObject extends UntypedJsonSchemaObject { @@ -1203,7 +1204,7 @@ public Document toDocument() { Document doc = new Document(super.toDocument()); if (!CollectionUtils.isEmpty(items)) { - doc.append("items", items.size() == 1 ? items.iterator().next() + doc.append("items", items.size() == 1 ? items.iterator().next().toDocument() : items.stream().map(JsonSchemaObject::toDocument).collect(Collectors.toList())); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java index 8f48ddd054..3efba4f058 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java @@ -41,6 +41,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Michał Kurcius */ public class JsonSchemaObjectUnitTests { @@ -269,6 +270,13 @@ public void arrayObjectShouldRenderItemsCorrectly() { .append("items", Arrays.asList(new Document("type", "string"), new Document("type", "boolean")))); } + @Test // DATAMONGO-2613 + public void arrayObjectShouldRenderItemsCorrectlyAsObjectIfContainsOnlyOneElement() { + + assertThat(array().items(Collections.singletonList(string())).toDocument()).isEqualTo(new Document("type", "array") + .append("items", new Document("type", "string"))); + } + @Test // DATAMONGO-1835 public void arrayObjectShouldRenderMaxItemsCorrectly() { From c9c005400cbae07c3e660b1efe76bf401a9af4e5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 20 Aug 2020 08:53:33 +0200 Subject: [PATCH 0247/1381] DATAMONGO-2613 - Polishing. Use the opportunity to remove public modifiers from touched test class. Original Pull Request: #883 --- .../schema/JsonSchemaObjectUnitTests.java | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java index 3efba4f058..89a0636967 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/JsonSchemaObjectUnitTests.java @@ -32,7 +32,6 @@ import org.bson.Document; import org.junit.jupiter.api.Test; - import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.*; @@ -43,14 +42,14 @@ * @author Mark Paluch * @author Michał Kurcius */ -public class JsonSchemaObjectUnitTests { +class JsonSchemaObjectUnitTests { // ----------------- // type from class // ----------------- @Test // DATAMONGO-1849 - public void primitiveType() { + void primitiveType() { assertThat(JsonSchemaObject.of(boolean.class).getTypes()).containsExactly(Type.booleanType()); assertThat(JsonSchemaObject.of(int.class).getTypes()).containsExactly(Type.intType()); @@ -61,7 +60,7 @@ public void primitiveType() { } @Test // DATAMONGO-1849 - public void objectType() { + void objectType() { assertThat(JsonSchemaObject.of(Object.class).getTypes()).containsExactly(Type.objectType()); assertThat(JsonSchemaObject.of(Map.class).getTypes()).containsExactly(Type.objectType()); @@ -69,12 +68,12 @@ public void objectType() { } @Test // DATAMONGO-1849 - public void binaryData() { + void binaryData() { assertThat(JsonSchemaObject.of(byte[].class).getTypes()).containsExactly(Type.binaryType()); } @Test // DATAMONGO-1849 - public void collectionType() { + void collectionType() { assertThat(JsonSchemaObject.of(Object[].class).getTypes()).containsExactly(Type.arrayType()); assertThat(JsonSchemaObject.of(Collection.class).getTypes()).containsExactly(Type.arrayType()); @@ -83,7 +82,7 @@ public void collectionType() { } @Test // DATAMONGO-1849 - public void dateType() { + void dateType() { assertThat(JsonSchemaObject.of(Date.class).getTypes()).containsExactly(Type.dateType()); } @@ -92,14 +91,14 @@ public void dateType() { // ----------------- @Test // DATAMONGO-1835 - public void objectObjectShouldRenderTypeCorrectly() { + void objectObjectShouldRenderTypeCorrectly() { assertThat(object().generatedDescription().toDocument()) .isEqualTo(new Document("type", "object").append("description", "Must be an object.")); } @Test // DATAMONGO-1835 - public void objectObjectShouldRenderNrPropertiesCorrectly() { + void objectObjectShouldRenderNrPropertiesCorrectly() { assertThat(object().propertiesCount(from(inclusive(10)).to(inclusive(20))).generatedDescription().toDocument()) .isEqualTo(new Document("type", "object").append("description", "Must be an object with [10-20] properties.") @@ -107,7 +106,7 @@ public void objectObjectShouldRenderNrPropertiesCorrectly() { } @Test // DATAMONGO-1835 - public void objectObjectShouldRenderRequiredPropertiesCorrectly() { + void objectObjectShouldRenderRequiredPropertiesCorrectly() { assertThat(object().required("spring", "data", "mongodb").generatedDescription().toDocument()) .isEqualTo(new Document("type", "object") @@ -116,7 +115,7 @@ public void objectObjectShouldRenderRequiredPropertiesCorrectly() { } @Test // DATAMONGO-1835 - public void objectObjectShouldRenderAdditionalPropertiesCorrectlyWhenBoolean() { + void objectObjectShouldRenderAdditionalPropertiesCorrectlyWhenBoolean() { assertThat(object().additionalProperties(true).generatedDescription().toDocument()).isEqualTo( new Document("type", "object").append("description", "Must be an object allowing additional properties.") @@ -128,7 +127,7 @@ public void objectObjectShouldRenderAdditionalPropertiesCorrectlyWhenBoolean() { } @Test // DATAMONGO-1835 - public void objectObjectShouldRenderPropertiesCorrectly() { + void objectObjectShouldRenderPropertiesCorrectly() { Document expected = new Document("type", "object") .append("description", "Must be an object defining restrictions for name, active.").append("properties", @@ -143,7 +142,7 @@ public void objectObjectShouldRenderPropertiesCorrectly() { } @Test // DATAMONGO-1835 - public void objectObjectShouldRenderNestedObjectPropertiesCorrectly() { + void objectObjectShouldRenderNestedObjectPropertiesCorrectly() { Document expected = new Document("type", "object") .append("description", "Must be an object defining restrictions for address.") @@ -159,7 +158,7 @@ public void objectObjectShouldRenderNestedObjectPropertiesCorrectly() { } @Test // DATAMONGO-1835 - public void objectObjectShouldRenderPatternPropertiesCorrectly() { + void objectObjectShouldRenderPatternPropertiesCorrectly() { Document expected = new Document("type", "object") .append("description", "Must be an object defining restrictions for patterns na.*.") @@ -171,7 +170,7 @@ public void objectObjectShouldRenderPatternPropertiesCorrectly() { } @Test // DATAMONGO-1849 - public void objectShouldIncludeRequiredNestedCorrectly() { + void objectShouldIncludeRequiredNestedCorrectly() { assertThat(object() // .properties( // @@ -186,21 +185,21 @@ public void objectShouldIncludeRequiredNestedCorrectly() { // ----------------- @Test // DATAMONGO-1835 - public void stringObjectShouldRenderTypeCorrectly() { + void stringObjectShouldRenderTypeCorrectly() { assertThat(string().generatedDescription().toDocument()) .isEqualTo(new Document("type", "string").append("description", "Must be a string.")); } @Test // DATAMONGO-1835 - public void stringObjectShouldRenderDescriptionCorrectly() { + void stringObjectShouldRenderDescriptionCorrectly() { assertThat(string().description("error msg").toDocument()) .isEqualTo(new Document("type", "string").append("description", "error msg")); } @Test // DATAMONGO-1835 - public void stringObjectShouldRenderRangeCorrectly() { + void stringObjectShouldRenderRangeCorrectly() { assertThat(string().length(from(inclusive(10)).to(inclusive(20))).generatedDescription().toDocument()) .isEqualTo(new Document("type", "string").append("description", "Must be a string with length [10-20].") @@ -208,7 +207,7 @@ public void stringObjectShouldRenderRangeCorrectly() { } @Test // DATAMONGO-1835 - public void stringObjectShouldRenderPatternCorrectly() { + void stringObjectShouldRenderPatternCorrectly() { assertThat(string().matching("^spring$").generatedDescription().toDocument()) .isEqualTo(new Document("type", "string").append("description", "Must be a string matching ^spring$.") @@ -220,7 +219,7 @@ public void stringObjectShouldRenderPatternCorrectly() { // ----------------- @Test // DATAMONGO-1835 - public void numberObjectShouldRenderMultipleOfCorrectly() { + void numberObjectShouldRenderMultipleOfCorrectly() { assertThat(number().multipleOf(3.141592F).generatedDescription().toDocument()) .isEqualTo(new Document("type", "number").append("description", "Must be a numeric value multiple of 3.141592.") @@ -228,7 +227,7 @@ public void numberObjectShouldRenderMultipleOfCorrectly() { } @Test // DATAMONGO-1835 - public void numberObjectShouldRenderMaximumCorrectly() { + void numberObjectShouldRenderMaximumCorrectly() { assertThat( number().within(Range.of(Bound.unbounded(), Bound.inclusive(3.141592F))).generatedDescription().toDocument()) @@ -244,7 +243,7 @@ public void numberObjectShouldRenderMaximumCorrectly() { } @Test // DATAMONGO-1835 - public void numberObjectShouldRenderMinimumCorrectly() { + void numberObjectShouldRenderMinimumCorrectly() { assertThat( number().within(Range.of(Bound.inclusive(3.141592F), Bound.unbounded())).generatedDescription().toDocument()) @@ -264,42 +263,42 @@ public void numberObjectShouldRenderMinimumCorrectly() { // ----------------- @Test // DATAMONGO-1835 - public void arrayObjectShouldRenderItemsCorrectly() { + void arrayObjectShouldRenderItemsCorrectly() { assertThat(array().items(Arrays.asList(string(), bool())).toDocument()).isEqualTo(new Document("type", "array") .append("items", Arrays.asList(new Document("type", "string"), new Document("type", "boolean")))); } @Test // DATAMONGO-2613 - public void arrayObjectShouldRenderItemsCorrectlyAsObjectIfContainsOnlyOneElement() { + void arrayObjectShouldRenderItemsCorrectlyAsObjectIfContainsOnlyOneElement() { - assertThat(array().items(Collections.singletonList(string())).toDocument()).isEqualTo(new Document("type", "array") - .append("items", new Document("type", "string"))); + assertThat(array().items(Collections.singletonList(string())).toDocument()) + .isEqualTo(new Document("type", "array").append("items", new Document("type", "string"))); } @Test // DATAMONGO-1835 - public void arrayObjectShouldRenderMaxItemsCorrectly() { + void arrayObjectShouldRenderMaxItemsCorrectly() { assertThat(array().maxItems(5).generatedDescription().toDocument()).isEqualTo(new Document("type", "array") .append("description", "Must be an array having size unbounded-5].").append("maxItems", 5)); } @Test // DATAMONGO-1835 - public void arrayObjectShouldRenderMinItemsCorrectly() { + void arrayObjectShouldRenderMinItemsCorrectly() { assertThat(array().minItems(5).generatedDescription().toDocument()).isEqualTo(new Document("type", "array") .append("description", "Must be an array having size [5-unbounded.").append("minItems", 5)); } @Test // DATAMONGO-1835 - public void arrayObjectShouldRenderUniqueItemsCorrectly() { + void arrayObjectShouldRenderUniqueItemsCorrectly() { assertThat(array().uniqueItems(true).generatedDescription().toDocument()).isEqualTo(new Document("type", "array") .append("description", "Must be an array of unique values.").append("uniqueItems", true)); } @Test // DATAMONGO-1835 - public void arrayObjectShouldRenderAdditionalItemsItemsCorrectly() { + void arrayObjectShouldRenderAdditionalItemsItemsCorrectly() { assertThat(array().additionalItems(true).generatedDescription().toDocument()) .isEqualTo(new Document("type", "array").append("description", "Must be an array with additional items.") @@ -314,7 +313,7 @@ public void arrayObjectShouldRenderAdditionalItemsItemsCorrectly() { // ----------------- @Test // DATAMONGO-1835 - public void booleanShouldRenderCorrectly() { + void booleanShouldRenderCorrectly() { assertThat(bool().generatedDescription().toDocument()) .isEqualTo(new Document("type", "boolean").append("description", "Must be a boolean.")); @@ -325,7 +324,7 @@ public void booleanShouldRenderCorrectly() { // ----------------- @Test // DATAMONGO-1835 - public void nullShouldRenderCorrectly() { + void nullShouldRenderCorrectly() { assertThat(nil().generatedDescription().toDocument()) .isEqualTo(new Document("type", "null").append("description", "Must be null.")); @@ -336,7 +335,7 @@ public void nullShouldRenderCorrectly() { // ----------------- @Test // DATAMONGO-1877 - public void dateShouldRenderCorrectly() { + void dateShouldRenderCorrectly() { assertThat(date().generatedDescription().toDocument()) .isEqualTo(new Document("bsonType", "date").append("description", "Must be a date.")); @@ -347,7 +346,7 @@ public void dateShouldRenderCorrectly() { // ----------------- @Test // DATAMONGO-1877 - public void timestampShouldRenderCorrectly() { + void timestampShouldRenderCorrectly() { assertThat(timestamp().generatedDescription().toDocument()) .isEqualTo(new Document("bsonType", "timestamp").append("description", "Must be a timestamp.")); @@ -358,35 +357,35 @@ public void timestampShouldRenderCorrectly() { // ----------------- @Test // DATAMONGO-1835 - public void typedObjectShouldRenderEnumCorrectly() { + void typedObjectShouldRenderEnumCorrectly() { assertThat(of(String.class).possibleValues(Arrays.asList("one", "two")).toDocument()) .isEqualTo(new Document("type", "string").append("enum", Arrays.asList("one", "two"))); } @Test // DATAMONGO-1835 - public void typedObjectShouldRenderAllOfCorrectly() { + void typedObjectShouldRenderAllOfCorrectly() { assertThat(of(Object.class).allOf(Arrays.asList(string())).toDocument()) .isEqualTo(new Document("type", "object").append("allOf", Arrays.asList(new Document("type", "string")))); } @Test // DATAMONGO-1835 - public void typedObjectShouldRenderAnyOfCorrectly() { + void typedObjectShouldRenderAnyOfCorrectly() { assertThat(of(String.class).anyOf(Arrays.asList(string())).toDocument()) .isEqualTo(new Document("type", "string").append("anyOf", Arrays.asList(new Document("type", "string")))); } @Test // DATAMONGO-1835 - public void typedObjectShouldRenderOneOfCorrectly() { + void typedObjectShouldRenderOneOfCorrectly() { assertThat(of(String.class).oneOf(Arrays.asList(string())).toDocument()) .isEqualTo(new Document("type", "string").append("oneOf", Arrays.asList(new Document("type", "string")))); } @Test // DATAMONGO-1835 - public void typedObjectShouldRenderNotCorrectly() { + void typedObjectShouldRenderNotCorrectly() { assertThat(untyped().notMatch(string()).toDocument()) .isEqualTo(new Document("not", new Document("type", "string"))); From c1da95f5dc1965db0c6a71a003bac00e0e6358aa Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Sep 2020 15:55:48 +0200 Subject: [PATCH 0248/1381] DATAMONGO-2621 - Adapt to changed array assertions in AssertJ. --- .../core/convert/MappingMongoConverterUnitTests.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 82a6840f9c..58687d3e28 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -1867,7 +1867,7 @@ public SomeInterface convert(String source) { } }; - converter.setCustomConversions(new MongoCustomConversions(Arrays.asList(enumConverter))); + converter.setCustomConversions(new MongoCustomConversions(Collections.singletonList(enumConverter))); converter.afterPropertiesSet(); DocWithInterfacedEnum result = converter.read(DocWithInterfacedEnum.class, document); @@ -1878,14 +1878,13 @@ public SomeInterface convert(String source) { @Test // DATAMONGO-1904 void readsNestedArraysCorrectly() { - List>> floats = Arrays.asList(Arrays.asList(Arrays.asList(1.0f, 2.0f))); + List>> floats = Collections.singletonList(Collections.singletonList(Arrays.asList(1.0f, 2.0f))); org.bson.Document document = new org.bson.Document("nestedFloats", floats); WithNestedLists result = converter.read(WithNestedLists.class, document); - assertThat(result.nestedFloats).hasSize(1); - assertThat(result.nestedFloats).isEqualTo(new float[][][] { { { 1.0f, 2.0f } } }); + assertThat(result.nestedFloats).hasDimensions(1, 1).isEqualTo(new float[][][] { { { 1.0f, 2.0f } } }); } @Test // DATAMONGO-1992 From 1a134aa4440461f6e4d5ea624dcad5085df46c15 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 14 Sep 2020 13:43:18 +0200 Subject: [PATCH 0249/1381] DATAMONGO-2618 - Fix visibility of ReplaceRootDocumentOperation. --- .../data/mongodb/core/aggregation/ReplaceRootOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index a63275feef..c891a73e42 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -175,7 +175,7 @@ public ReplaceRootOperation withDocument(Document document) { * * @author Mark Paluch */ - static class ReplaceRootDocumentOperation extends ReplaceRootOperation { + public static class ReplaceRootDocumentOperation extends ReplaceRootOperation { private final static ReplacementDocument EMPTY = new ReplacementDocument(); private final ReplacementDocument current; From 1bdcb884306b7c8e05f3044689be0f1098373c3d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 10:15:54 +0200 Subject: [PATCH 0250/1381] DATAMONGO-2592 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index d86f167834..a333168f42 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.20.RELEASE (2020-09-16) +---------------------------------------------- +* DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. +* DATAMONGO-2613 - ArrayJsonSchemaObject incorrectly mapped to Document. +* DATAMONGO-2592 - Release 2.1.20 (Lovelace SR20). + + Changes in version 3.0.3.RELEASE (2020-08-12) --------------------------------------------- * DATAMONGO-2601 - Consider Unit a void type in Coroutine repositories. @@ -3139,5 +3146,6 @@ Repository + From 415ceeef63080492fe90d4d6912704cdaea5ed3c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 10:52:37 +0200 Subject: [PATCH 0251/1381] DATAMONGO-2593 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index a333168f42..6b65106621 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.10.RELEASE (2020-09-16) +---------------------------------------------- +* DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. +* DATAMONGO-2613 - ArrayJsonSchemaObject incorrectly mapped to Document. +* DATAMONGO-2599 - Ambiguous field mapping detected for enum java.time.temporal.ChronoUnit. +* DATAMONGO-2593 - Release 2.2.10 (Moore SR10). + + Changes in version 2.1.20.RELEASE (2020-09-16) ---------------------------------------------- * DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. @@ -3147,5 +3155,6 @@ Repository + From c9cfe7acd6c8a28555a4d17cb11e50e1c9aa3a6c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 11:42:29 +0200 Subject: [PATCH 0252/1381] DATAMONGO-2609 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 6b65106621..2aee9c3e9b 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.4.RELEASE (2020-09-16) +--------------------------------------------- +* DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. +* DATAMONGO-2613 - ArrayJsonSchemaObject incorrectly mapped to Document. +* DATAMONGO-2609 - Release 3.0.4 (Neumann SR4). + + Changes in version 2.2.10.RELEASE (2020-09-16) ---------------------------------------------- * DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. @@ -3156,5 +3163,6 @@ Repository + From 61f4770b4abb2a717b866e1844350b3b09dae22d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 13:56:57 +0200 Subject: [PATCH 0253/1381] DATAMONGO-2608 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 2aee9c3e9b..2677a17a2a 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.0-RC1 (2020-09-16) +----------------------------------------- +* DATAMONGO-2621 - Adapt to changed array assertions in AssertJ. +* DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. +* DATAMONGO-2613 - ArrayJsonSchemaObject incorrectly mapped to Document. +* DATAMONGO-2608 - Release 3.1 RC1 (2020.0.0). + + Changes in version 3.0.4.RELEASE (2020-09-16) --------------------------------------------- * DATAMONGO-2618 - ReplaceRootDocumentOperation not visible. @@ -3164,5 +3172,6 @@ Repository + From 6034fc1cbde98eb22146b71f75f6886433e23e31 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 13:57:08 +0200 Subject: [PATCH 0254/1381] DATAMONGO-2608 - Prepare 3.1 RC1 (2020.0.0). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9d352e7658..404fd8b512 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-SNAPSHOT + 2.4.0-RC1 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-SNAPSHOT + 2.4.0-RC1 4.1.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 39953ea2f9..ecfc557c9b 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.1 M2 (2020.0.0) +Spring Data MongoDB 3.1 RC1 (2020.0.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -17,3 +17,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From b4befc36c0e5a97a2e3eba40dd69a8c21b1badb5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 13:57:41 +0200 Subject: [PATCH 0255/1381] DATAMONGO-2608 - Release version 3.1 RC1 (2020.0.0). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 404fd8b512..2127338f13 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC1 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a85b081e26..2b5226e2a0 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC1 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 33014c7c4f..cce83205eb 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC1 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ea401d5618..658df253c3 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC1 ../pom.xml From edfd07a3d0d4ac370543dc2f6f3079aedacec574 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 14:05:24 +0200 Subject: [PATCH 0256/1381] DATAMONGO-2608 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2127338f13..404fd8b512 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC1 + 3.1.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 2b5226e2a0..a85b081e26 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC1 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index cce83205eb..33014c7c4f 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC1 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 658df253c3..ea401d5618 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC1 + 3.1.0-SNAPSHOT ../pom.xml From 046cbb52a11cbb85dddc97f04498bd2f2453cca3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 16 Sep 2020 14:05:28 +0200 Subject: [PATCH 0257/1381] DATAMONGO-2608 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 404fd8b512..9d352e7658 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-RC1 + 2.4.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-RC1 + 2.4.0-SNAPSHOT 4.1.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 965a34efd3bce372d6f6a6d7bf1319173191c01b Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Fri, 18 Sep 2020 11:08:38 -0500 Subject: [PATCH 0258/1381] DATAMONGO-2629 - Only test other versions for local changes on main branch. --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 62ea203246..16a4d35925 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -93,7 +93,7 @@ pipeline { stage("Test other configurations") { when { - anyOf { + allOf { branch 'master' not { triggeredBy 'UpstreamCause' } } From 91c39e2825076d7bc2394f62830caa84b065a41e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Sep 2020 14:53:19 +0200 Subject: [PATCH 0259/1381] DATAMONGO-2630 - Add support for suspend repository query methods returning List. --- .../repository/query/ReactiveMongoQueryMethod.java | 4 ++-- .../ReactiveMongoQueryMethodCoroutineUnitTests.kt | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java index 97fc3d55d5..4659653bfd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java @@ -94,8 +94,8 @@ public ReactiveMongoQueryMethod(Method method, RepositoryMetadata metadata, Proj } this.method = method; - this.isCollectionQuery = Lazy.of(() -> !(isPageQuery() || isSliceQuery()) - && ReactiveWrappers.isMultiValueType(metadata.getReturnType(method).getType())); + this.isCollectionQuery = Lazy.of(() -> (!(isPageQuery() || isSliceQuery()) + && ReactiveWrappers.isMultiValueType(metadata.getReturnType(method).getType()) || super.isCollectionQuery())); } /* diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt index ea77b86e93..04d3ce99dd 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethodCoroutineUnitTests.kt @@ -39,6 +39,8 @@ class ReactiveMongoQueryMethodCoroutineUnitTests { suspend fun findSuspendAllByName(): Flow fun findAllByName(): Flow + + suspend fun findSuspendByName(): List } @Test // DATAMONGO-2562 @@ -58,4 +60,13 @@ class ReactiveMongoQueryMethodCoroutineUnitTests { assertThat(queryMethod.isCollectionQuery).isTrue() } + + @Test // DATAMONGO-2630 + internal fun `should consider suspended methods returning List as collection queries`() { + + val method = PersonRepository::class.java.getMethod("findSuspendByName", Continuation::class.java) + val queryMethod = ReactiveMongoQueryMethod(method, DefaultRepositoryMetadata(PersonRepository::class.java), projectionFactory, MongoMappingContext()) + + assertThat(queryMethod.isCollectionQuery).isTrue() + } } From b2927ab419f56252ef8e54c0e9051d2350eebcc1 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 28 Sep 2020 12:18:33 +0200 Subject: [PATCH 0260/1381] DATAMONGO-2633 - Fix json parsing of nested arrays in ParameterBindingDocumentCodec. Original pull request: #888. --- .../util/json/ParameterBindingDocumentCodec.java | 10 +--------- .../util/json/ParameterBindingJsonReaderUnitTests.java | 9 +++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index 566ff603a5..900b41e7fd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -365,15 +365,7 @@ private List readList(final BsonReader reader, final DecoderContext deco reader.readStartArray(); List list = new ArrayList<>(); while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { - - // Spring Data Customization START - Object listValue = readValue(reader, decoderContext); - if (listValue instanceof Collection) { - list.addAll((Collection) listValue); - break; - } - list.add(listValue); - // Spring Data Customization END + list.add(readValue(reader, decoderContext)); } reader.readEndArray(); return list; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 3403f304dc..1335c04b20 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -374,6 +374,15 @@ void shouldParseRegexWithPlaceholderCorrectly() { .isEqualTo(Document.parse("{ $and: [{'fieldA': {$in: [/ABC.*/, /CDE.*F/]}}, {'fieldB': {$ne: null}}]}")); } + @Test // DATAMONGO-2633 + void shouldParseNestedArrays() { + + Document target = parse("{ 'stores.location' : { $geoWithin: { $centerSphere: [ [ ?0, 48.799029 ] , ?1 ] } } }", + 1.948516D, 0.004D); + assertThat(target).isEqualTo(Document + .parse("{ 'stores.location' : { $geoWithin: { $centerSphere: [ [ 1.948516, 48.799029 ] , 0.004 ] } } }")); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); From 85022d24f343a5c34295232ff6e4efd802ac6b30 Mon Sep 17 00:00:00 2001 From: owen-q Date: Fri, 7 Jun 2019 23:23:32 +0900 Subject: [PATCH 0261/1381] DATAMONGO-2294 - Support query projections with collection types. Query include/exclude now accepts a vararg array of fields to specify multiple fields at once. Original pull request: #761. --- .../data/mongodb/core/query/Field.java | 20 +++++++++ .../data/mongodb/core/MongoTemplateTests.java | 43 ++++++++++++++++--- .../mongodb/core/query/FieldUnitTests.java | 21 +++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java index 4940a857e9..eeaed61140 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java @@ -15,10 +15,13 @@ */ package org.springframework.data.mongodb.core.query; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import lombok.EqualsAndHashCode; + import org.bson.Document; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -30,6 +33,7 @@ * @author Patryk Wasik * @author Christoph Strobl * @author Mark Paluch + * @author Owen Q */ public class Field { @@ -44,11 +48,27 @@ public Field include(String key) { return this; } + public Field includes(String... keys) { + Assert.notNull(keys, "Keys must not be null!"); + Assert.notEmpty(keys, "Keys must not be empty!"); + + Arrays.asList(keys).stream().forEach(this::include); + return this; + } + public Field exclude(String key) { criteria.put(key, Integer.valueOf(0)); return this; } + public Field excludes(String... keys) { + Assert.notNull(keys, "Keys must not be null!"); + Assert.notEmpty(keys, "Keys must not be empty!"); + + Arrays.asList(keys).stream().forEach(this::exclude); + return this; + } + public Field slice(String key, int size) { slices.put(key, Integer.valueOf(size)); return this; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index f7c308a2f2..96b6e1001b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -15,18 +15,18 @@ */ package org.springframework.data.mongodb.core; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.*; +import static org.junit.Assume.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.core.query.Update.*; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.Value; -import lombok.experimental.Wither; - import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.math.BigInteger; @@ -38,6 +38,13 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; +import lombok.experimental.Wither; + import org.bson.types.ObjectId; import org.joda.time.DateTime; import org.junit.jupiter.api.AfterEach; @@ -91,6 +98,7 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBRef; +import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; @@ -3669,6 +3677,27 @@ public void shouldNotConvertStringToObjectIdForNonIdField() { assertThat(target.inner.id).isEqualTo(innerId); } + @Test // DATAMONGO-2294 + public void shouldProjectWithCollections() { + + MyPerson person = new MyPerson("Walter"); + person.address = new Address("TX", "Austin"); + template.save(person); + + Query queryByChainedInclude = query(where("name").is("Walter")); + queryByChainedInclude.fields().include("id").include("name"); + + Query queryByCollectionInclude = query(where("name").is("Walter")); + queryByCollectionInclude.fields().includes("id", "name"); + + MyPerson first = template.findAndReplace(queryByChainedInclude, new MyPerson("Walter")); + MyPerson second = template.findAndReplace(queryByCollectionInclude, new MyPerson("Walter")); + + assertThat(first).isEqualTo(second); + assertThat(first.address).isNull(); + assertThat(second.address).isNull(); + } + @Test // DATAMONGO-2451 public void sortOnIdFieldWithExplicitTypeShouldWork() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java index ee312f7846..e48dae2455 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java @@ -23,6 +23,7 @@ * Unit tests for {@link DocumentField}. * * @author Oliver Gierke + * @author Owen Q */ public class FieldUnitTests { @@ -36,6 +37,16 @@ public void sameObjectSetupCreatesEqualField() { assertThat(right).isEqualTo(left); } + @Test // DATAMONGO-2294 + public void sameObjectSetupCreatesEqualFieldByCollections() { + + Field left = new Field().includes("foo", "bar"); + Field right = new Field().include("foo").include("bar"); + + assertThat(left, is(right)); + assertThat(right, is(left)); + } + @Test public void differentObjectSetupCreatesEqualField() { @@ -45,4 +56,14 @@ public void differentObjectSetupCreatesEqualField() { assertThat(left).isNotEqualTo(right); assertThat(right).isNotEqualTo(left); } + + @Test // DATAMONGO-2294 + public void differentObjectSetupCreatesEqualFieldByCollections() { + + Field left = new Field().includes("foo", "bar"); + Field right = new Field().include("foo").include("zoo"); + + assertThat(left, is(not(right))); + assertThat(right, is(not(left))); + } } From c0581c4943154ee0f0f2bdeca64a3d30bcab5210 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 5 Oct 2020 16:58:22 +0200 Subject: [PATCH 0262/1381] DATAMONGO-2294 - Polishing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganize imports after Delomboking. Use for-loop instead of Stream.forEach(…). Add Javadoc to methods. Add since tags. Simplify tests. Original pull request: #761. --- .../data/mongodb/core/query/Field.java | 112 ++++++++++++++---- .../data/mongodb/core/MongoTemplateTests.java | 33 ++---- .../mongodb/core/query/FieldUnitTests.java | 28 ++--- 3 files changed, 112 insertions(+), 61 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java index eeaed61140..8c822e7156 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java @@ -15,19 +15,19 @@ */ package org.springframework.data.mongodb.core.query; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import lombok.EqualsAndHashCode; - import org.bson.Document; + import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** + * Field projection. + * * @author Thomas Risberg * @author Oliver Gierke * @author Patryk Wasik @@ -37,50 +37,112 @@ */ public class Field { - private final Map criteria = new HashMap(); - private final Map slices = new HashMap(); - private final Map elemMatchs = new HashMap(); + private final Map criteria = new HashMap<>(); + private final Map slices = new HashMap<>(); + private final Map elemMatchs = new HashMap<>(); private @Nullable String positionKey; private int positionValue; - public Field include(String key) { - criteria.put(key, Integer.valueOf(1)); + /** + * Include a single {@code field} to be returned by the query operation. + * + * @param field the document field name to be included. + * @return {@code this} field projection instance. + */ + public Field include(String field) { + + Assert.notNull(field, "Key must not be null!"); + + criteria.put(field, 1); + return this; } - public Field includes(String... keys) { - Assert.notNull(keys, "Keys must not be null!"); - Assert.notEmpty(keys, "Keys must not be empty!"); + /** + * Include one or more {@code fields} to be returned by the query operation. + * + * @param fields the document field names to be included. + * @return {@code this} field projection instance. + * @since 3.1 + */ + public Field include(String... fields) { + + Assert.notNull(fields, "Keys must not be null!"); + + for (String key : fields) { + criteria.put(key, 1); + } - Arrays.asList(keys).stream().forEach(this::include); return this; } - public Field exclude(String key) { - criteria.put(key, Integer.valueOf(0)); + /** + * Exclude a single {@code field} from being returned by the query operation. + * + * @param field the document field name to be included. + * @return {@code this} field projection instance. + */ + public Field exclude(String field) { + + Assert.notNull(field, "Key must not be null!"); + + criteria.put(field, 0); + return this; } - public Field excludes(String... keys) { - Assert.notNull(keys, "Keys must not be null!"); - Assert.notEmpty(keys, "Keys must not be empty!"); + /** + * Exclude one or more {@code fields} from being returned by the query operation. + * + * @param fields the document field names to be included. + * @return {@code this} field projection instance. + * @since 3.1 + */ + public Field exclude(String... fields) { + + Assert.notNull(fields, "Keys must not be null!"); + + for (String key : fields) { + criteria.put(key, 0); + } - Arrays.asList(keys).stream().forEach(this::exclude); return this; } - public Field slice(String key, int size) { - slices.put(key, Integer.valueOf(size)); + /** + * Project a {@code $slice} of the array {@code field} using the first {@code size} elements. + * + * @param field the document field name to project, must be an array field. + * @param size the number of elements to include. + * @return {@code this} field projection instance. + */ + public Field slice(String field, int size) { + + Assert.notNull(field, "Key must not be null!"); + + slices.put(field, size); + return this; } - public Field slice(String key, int offset, int size) { - slices.put(key, new Integer[] { Integer.valueOf(offset), Integer.valueOf(size) }); + /** + * Project a {@code $slice} of the array {@code field} using the first {@code size} elements starting at + * {@code offset}. + * + * @param field the document field name to project, must be an array field. + * @param offset the offset to start at. + * @param size the number of elements to include. + * @return {@code this} field projection instance. + */ + public Field slice(String field, int offset, int size) { + + slices.put(field, new Integer[] { offset, size }); return this; } - public Field elemMatch(String key, Criteria elemMatchCriteria) { - elemMatchs.put(key, elemMatchCriteria); + public Field elemMatch(String field, Criteria elemMatchCriteria) { + + elemMatchs.put(field, elemMatchCriteria); return this; } @@ -90,7 +152,7 @@ public Field elemMatch(String key, Criteria elemMatchCriteria) { * * @param field query array field, must not be {@literal null} or empty. * @param value - * @return + * @return {@code this} field projection instance. */ public Field position(String field, int value) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 96b6e1001b..8865d5a619 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -15,18 +15,18 @@ */ package org.springframework.data.mongodb.core; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.*; -import static org.junit.Assume.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; import static org.springframework.data.mongodb.core.query.Update.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; +import lombok.With; + import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.math.BigInteger; @@ -38,13 +38,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.Value; -import lombok.experimental.Wither; - import org.bson.types.ObjectId; import org.joda.time.DateTime; import org.junit.jupiter.api.AfterEach; @@ -98,7 +91,6 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBRef; -import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; @@ -1847,7 +1839,7 @@ public void queryShouldSupportRealAndAliasedPropertyNamesForFieldInclusions() { assertThat(result.property3).isEqualTo(obj.property3); } - @Test // DATAMONGO-702 + @Test // DATAMONGO-702, DATAMONGO-2294 public void queryShouldSupportRealAndAliasedPropertyNamesForFieldExclusions() { ObjectWith3AliasedFields obj = new ObjectWith3AliasedFields(); @@ -1860,8 +1852,7 @@ public void queryShouldSupportRealAndAliasedPropertyNamesForFieldExclusions() { Query query = new Query(Criteria.where("id").is(obj.id)); query.fields() // - .exclude("property2") // real property name - .exclude("prop3"); // aliased property name + .exclude("property2", "prop3"); // real property name, aliased property name ObjectWith3AliasedFields result = template.findOne(query, ObjectWith3AliasedFields.class); @@ -3688,7 +3679,7 @@ public void shouldProjectWithCollections() { queryByChainedInclude.fields().include("id").include("name"); Query queryByCollectionInclude = query(where("name").is("Walter")); - queryByCollectionInclude.fields().includes("id", "name"); + queryByCollectionInclude.fields().include("id", "name"); MyPerson first = template.findAndReplace(queryByChainedInclude, new MyPerson("Walter")); MyPerson second = template.findAndReplace(queryByCollectionInclude, new MyPerson("Walter")); @@ -4209,7 +4200,7 @@ public String toString() { // DATAMONGO-1992 @AllArgsConstructor - @Wither + @With static class ImmutableVersioned { final @Id String id; @@ -4222,7 +4213,7 @@ public ImmutableVersioned() { } @Value - @Wither + @With static class ImmutableAudited { @Id String id; @LastModifiedDate Instant modified; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java index e48dae2455..05e39f4295 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/FieldUnitTests.java @@ -15,40 +15,40 @@ */ package org.springframework.data.mongodb.core.query; -import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.test.util.Assertions.*; import org.junit.jupiter.api.Test; /** - * Unit tests for {@link DocumentField}. + * Unit tests for {@link Field}. * * @author Oliver Gierke * @author Owen Q + * @author Mark Paluch */ -public class FieldUnitTests { +class FieldUnitTests { @Test - public void sameObjectSetupCreatesEqualField() { + void sameObjectSetupCreatesEqualField() { Field left = new Field().elemMatch("key", Criteria.where("foo").is("bar")); Field right = new Field().elemMatch("key", Criteria.where("foo").is("bar")); assertThat(left).isEqualTo(right); assertThat(right).isEqualTo(left); + assertThat(left.getFieldsObject()).isEqualTo("{key: { $elemMatch: {foo:\"bar\"}}}"); } @Test // DATAMONGO-2294 - public void sameObjectSetupCreatesEqualFieldByCollections() { + void rendersInclusionCorrectly() { - Field left = new Field().includes("foo", "bar"); - Field right = new Field().include("foo").include("bar"); + Field fields = new Field().include("foo", "bar").include("baz"); - assertThat(left, is(right)); - assertThat(right, is(left)); + assertThat(fields.getFieldsObject()).isEqualTo("{foo:1, bar:1, baz:1}"); } @Test - public void differentObjectSetupCreatesEqualField() { + void differentObjectSetupCreatesEqualField() { Field left = new Field().elemMatch("key", Criteria.where("foo").is("bar")); Field right = new Field().elemMatch("key", Criteria.where("foo").is("foo")); @@ -58,12 +58,10 @@ public void differentObjectSetupCreatesEqualField() { } @Test // DATAMONGO-2294 - public void differentObjectSetupCreatesEqualFieldByCollections() { + void rendersExclusionCorrectly() { - Field left = new Field().includes("foo", "bar"); - Field right = new Field().include("foo").include("zoo"); + Field fields = new Field().exclude("foo", "bar").exclude("baz"); - assertThat(left, is(not(right))); - assertThat(right, is(not(left))); + assertThat(fields.getFieldsObject()).isEqualTo("{foo:0, bar:0, baz:0}"); } } From b879ec8c0f1a5ce8ebc146ae41bd55e5b48d8ac1 Mon Sep 17 00:00:00 2001 From: Yoann de Martino Date: Wed, 5 Aug 2020 09:00:58 +0200 Subject: [PATCH 0263/1381] DATAMONGO-2596 - Introduce extension to render KProperty/KPropertyPath as property path. Original pull request: #880. --- .../data/mongodb/core/query/KPropertyPath.kt | 9 ++++++-- .../mongodb/core/query/KPropertyPathTests.kt | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt index becfe9ca68..d83463f439 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt @@ -22,12 +22,17 @@ import kotlin.reflect.KProperty1 * Abstraction of a property path consisting of [KProperty]. * @author Tjeu Kayim * @author Mark Paluch + * @author Yoann de Martino * @since 2.2 */ class KPropertyPath( internal val parent: KProperty, internal val child: KProperty1 -) : KProperty by child +) : KProperty by child { + override fun toString(): String { + return asString(this) + } +} /** * Recursively construct field name for a nested property. @@ -45,7 +50,7 @@ internal fun asString(property: KProperty<*>): String { * Builds [KPropertyPath] from Property References. * Refer to a field in an embedded/nested document. * - * For example, referring to the field "book.author": + * For example, referring to the field "author.name": * ``` * Book::author / Author::name isEqualTo "Herman Melville" * ``` diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt index 03d68f7249..cb41e7b9cd 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt @@ -20,6 +20,7 @@ import org.junit.Test /** * @author Tjeu Kayim + * @author Yoann de Martino */ class KPropertyPathTests { @@ -60,6 +61,26 @@ class KPropertyPathTests { assertThat(property).isEqualTo("entity.book.author.name") } + @Test + fun `Convert nested KProperty to field name using toString()`() { + + val property = (Book::author / Author::name).toString() + + assertThat(property).isEqualTo("author.name") + } + + + @Test + fun `Convert triple nested KProperty to field name using toString()`() { + + class Entity(val book: Book) + class AnotherEntity(val entity: Entity) + + val property = (AnotherEntity::entity / Entity::book / Book::author / Author::name).toString() + + assertThat(property).isEqualTo("entity.book.author.name") + } + class Book(val title: String, val author: Author) class Author(val name: String) } From 4548d0782671003ff3df5bcefbe20ee1c0e3f03e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 6 Oct 2020 10:16:50 +0200 Subject: [PATCH 0264/1381] DATAMONGO-2596 - Polishing. Refactor KPropertyPath.toString() into KProperty.asPath() extension function to allow rendering simple properties and property paths into a String property path. Original pull request: #880. --- .../data/mongodb/core/query/KPropertyPath.kt | 7 ++--- .../core/query/KPropertyPathExtensions.kt | 26 +++++++++++++++++++ .../mongodb/core/query/KPropertyPathTests.kt | 22 ++++++++++++---- src/main/asciidoc/new-features.adoc | 1 + 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt index d83463f439..daa008af7f 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt @@ -20,6 +20,7 @@ import kotlin.reflect.KProperty1 /** * Abstraction of a property path consisting of [KProperty]. + * * @author Tjeu Kayim * @author Mark Paluch * @author Yoann de Martino @@ -28,11 +29,7 @@ import kotlin.reflect.KProperty1 class KPropertyPath( internal val parent: KProperty, internal val child: KProperty1 -) : KProperty by child { - override fun toString(): String { - return asString(this) - } -} +) : KProperty by child /** * Recursively construct field name for a nested property. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt new file mode 100644 index 0000000000..10a23bce6d --- /dev/null +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2020 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 + * + * https://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.query + +import kotlin.reflect.KProperty + +/** + * Extension for [KProperty] providing an `toPath` function to render a [KProperty] as property path. + * + * @author Mark Paluch + * @since 3.1 + */ +fun KProperty<*>.toPath(): String = asString(this) diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt index cb41e7b9cd..8a13140bac 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt @@ -19,8 +19,11 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.Test /** + * Unit tests for [KPropertyPath] and its extensions. + * * @author Tjeu Kayim * @author Yoann de Martino + * @author Mark Paluch */ class KPropertyPathTests { @@ -62,21 +65,30 @@ class KPropertyPathTests { } @Test - fun `Convert nested KProperty to field name using toString()`() { + fun `Convert simple KProperty to property path using toPath`() { - val property = (Book::author / Author::name).toString() + class AnotherEntity(val entity: String) - assertThat(property).isEqualTo("author.name") + val property = (AnotherEntity::entity).toPath() + + assertThat(property).isEqualTo("entity") } + @Test + fun `Convert nested KProperty to field name using toPath()`() { + + val property = (Book::author / Author::name).toPath() + + assertThat(property).isEqualTo("author.name") + } @Test - fun `Convert triple nested KProperty to field name using toString()`() { + fun `Convert triple nested KProperty to property path using toPath`() { class Entity(val book: Book) class AnotherEntity(val entity: Entity) - val property = (AnotherEntity::entity / Entity::book / Book::author / Author::name).toString() + val property = (AnotherEntity::entity / Entity::book / Book::author / Author::name).toPath() assertThat(property).isEqualTo("entity.book.author.name") } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 7727e28391..071d56f32b 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -7,6 +7,7 @@ * <> enabled through `@EnableReactiveMongoAuditing`. `@EnableMongoAuditing` no longer registers `ReactiveAuditingEntityCallback`. * Reactive SpEL support in `@Query` and `@Aggregation` query methods. * Aggregation hints via `AggregationOptions.builder().hint(bson).build()`. +* Extension Function `KProperty.asPath()` to render property references into a property path representation. [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 From 230c32041a38ad0fb142c645b603d8c8e0a893d2 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 17 Sep 2020 14:02:10 +0200 Subject: [PATCH 0265/1381] DATAMONGO-2622 - Add support for $unionWith aggregation stage. We now support the $unionWith aggregation stage via the UnionWithOperation that performs a union of two collections by combining pipeline results, potentially containing duplicates, into a single result set that is handed over to the next stage. In order to remove duplicates it is possible to append a GroupOperation right after UnionWithOperation. If the UnionWithOperation uses a pipeline to process documents, field names within the pipeline will be treated as is. In order to map domain type property names to actual field names (considering potential org.springframework.data.mongodb.core.mapping.Field annotations) make sure the enclosing aggregation is a TypedAggregation and provide the target type for the $unionWith stage via mapFieldsTo(Class). Original pull request: #886. --- .../data/mongodb/core/AggregationUtil.java | 14 +- .../data/mongodb/core/MongoTemplate.java | 4 +- .../core/aggregation/AggregationPipeline.java | 35 ++++ ...osedFieldsAggregationOperationContext.java | 8 + .../TypeBasedAggregationOperationContext.java | 13 ++ .../core/aggregation/UnionWithOperation.java | 170 ++++++++++++++++++ .../UnionWithOperationUnitTests.java | 129 +++++++++++++ 7 files changed, 366 insertions(+), 7 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java index 0f956a317b..b9c4be1d0d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java @@ -28,6 +28,7 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; import org.springframework.data.mongodb.core.aggregation.CountOperation; +import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -75,12 +76,17 @@ AggregationOperationContext prepareAggregationContext(Aggregation aggregation, return context; } - if (aggregation instanceof TypedAggregation) { - return new TypeBasedAggregationOperationContext(((TypedAggregation) aggregation).getInputType(), mappingContext, - queryMapper); + if (!(aggregation instanceof TypedAggregation)) { + return Aggregation.DEFAULT_CONTEXT; } - return Aggregation.DEFAULT_CONTEXT; + Class inputType = ((TypedAggregation) aggregation).getInputType(); + + if (aggregation.getPipeline().requiresRelaxedChecking()) { + return new RelaxedTypeBasedAggregationOperationContext(inputType, mappingContext, queryMapper); + } + + return new TypeBasedAggregationOperationContext(inputType, mappingContext, queryMapper); } /** 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 97deaae467..227ba00636 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 @@ -1977,9 +1977,7 @@ public AggregationResults aggregate(TypedAggregation aggregation, Stri Assert.notNull(aggregation, "Aggregation pipeline must not be null!"); - AggregationOperationContext context = new TypeBasedAggregationOperationContext(aggregation.getInputType(), - mappingContext, queryMapper); - return aggregate(aggregation, inputCollectionName, outputType, context); + return aggregate(aggregation, inputCollectionName, outputType, null); } /* (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java index 8c4b0ed10d..083daa6d81 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java @@ -45,6 +45,8 @@ public AggregationPipeline() { * @param aggregationOperations must not be {@literal null}. */ public AggregationPipeline(List aggregationOperations) { + + Assert.notNull(aggregationOperations, "AggregationOperations must not be null!"); pipeline = new ArrayList<>(aggregationOperations); } @@ -108,4 +110,37 @@ void verify() { private boolean isLast(AggregationOperation aggregationOperation) { return pipeline.indexOf(aggregationOperation) == pipeline.size() - 1; } + + /** + * @return {@literal true} if field names might get computed by one of the pipeline stages, that the + * {@link AggregationOperationContext} might not be aware of. A strongly typed context might fail to resolve + * field references, so if {@literal true} usage of a {@link RelaxedTypeBasedAggregationOperationContext} + * might be the better choice. + * @since 3.1 + */ + public boolean requiresRelaxedChecking() { + return pipelineContainsValueOfType(UnionWithOperation.class); + } + + /** + * @return {@literal true} if the pipeline does not contain any stages. + * @since 3.1 + */ + public boolean isEmpty() { + return pipeline.isEmpty(); + } + + private boolean pipelineContainsValueOfType(Class type) { + + if (isEmpty()) { + return false; + } + + for (Object element : pipeline) { + if (type.isInstance(element)) { + return true; + } + } + return false; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java index d802fa4d12..f0c2b60a26 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java @@ -149,4 +149,12 @@ protected FieldReference resolveExposedField(@Nullable Field field, String name) } return null; } + + /** + * @return obtain the root context used to resolve references. + * @since 3.1 + */ + AggregationOperationContext getRootContext() { + return rootContext; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java index 5ba22e9603..aab2ffe5f5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java @@ -133,6 +133,19 @@ public Fields getFields(Class type) { */ @Override public AggregationOperationContext continueOnMissingFieldReference() { + return continueOnMissingFieldReference(type); + } + + /** + * This toggle allows the {@link AggregationOperationContext context} to use any given field name without checking for + * its existence. Typically the {@link AggregationOperationContext} fails when referencing unknown fields, those that + * are not present in one of the previous stages or the input source, throughout the pipeline. + * + * @param type The domain type to map fields to. + * @return a more relaxed {@link AggregationOperationContext}. + * @since 3.1 + */ + public AggregationOperationContext continueOnMissingFieldReference(Class type) { return new RelaxedTypeBasedAggregationOperationContext(type, mappingContext, mapper); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java new file mode 100644 index 0000000000..c30e8c7ec1 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java @@ -0,0 +1,170 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import java.util.Arrays; +import java.util.List; + +import org.bson.Document; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * The $unionWith aggregation + * stage (available since MongoDB 4.4) performs a union of two collections by combining pipeline results, potentially + * containing duplicates, into a single result set that is handed over to the next stage.
      + * In order to remove duplicates it is possible to append a {@link GroupOperation} right after + * {@link UnionWithOperation}. + *

      + * If the {@link UnionWithOperation} uses a + * pipeline + * to process documents, field names within the pipeline will be treated as is. In order to map domain type property + * names to actual field names (considering potential {@link org.springframework.data.mongodb.core.mapping.Field} + * annotations) make sure the enclosing aggregation is a {@link TypedAggregation} and provide the target type for the + * {@code $unionWith} stage via {@link #mapFieldsTo(Class)}. + * + * @author Christoph Strobl + * @see Aggregation Pipeline Stage: + * $unionWith + * @since 3.1 + */ +public class UnionWithOperation implements AggregationOperation { + + private final String collection; + + @Nullable // + private final AggregationPipeline pipeline; + + @Nullable // + private final Class domainType; + + public UnionWithOperation(String collection, @Nullable AggregationPipeline pipeline, @Nullable Class domainType) { + + this.collection = collection; + this.pipeline = pipeline; + this.domainType = domainType; + } + + /** + * Set the name of the collection from which pipeline results should be included in the result set.
      + * The collection name is used to set the {@code coll} parameter of {@code $unionWith}. + * + * @param collection the MongoDB collection name. Must not be {@literal null}. + * @return new instance of {@link UnionWithOperation}. + * @throws IllegalArgumentException if the required argument is {@literal null}. + */ + public static UnionWithOperation unionWith(String collection) { + + Assert.notNull(collection, "Collection must not be null!"); + return new UnionWithOperation(collection, null, null); + } + + /** + * Set the {@link AggregationPipeline} to apply to the specified collection. The pipeline corresponds to the optional + * {@code pipeline} field of the {@code $unionWith} aggregation stage and is used to compute the documents going into + * the result set. + * + * @param pipeline the {@link AggregationPipeline} that computes the documents. Must not be {@literal null}. + * @return new instance of {@link UnionWithOperation}. + * @throws IllegalArgumentException if the required argument is {@literal null}. + */ + public UnionWithOperation pipeline(AggregationPipeline pipeline) { + return new UnionWithOperation(collection, pipeline, domainType); + } + + /** + * Set the aggregation pipeline stages to apply to the specified collection. The pipeline corresponds to the optional + * {@code pipeline} field of the {@code $unionWith} aggregation stage and is used to compute the documents going into + * the result set. + * + * @param aggregationStages the aggregation pipeline stages that compute the documents. Must not be {@literal null}. + * @return new instance of {@link UnionWithOperation}. + * @throws IllegalArgumentException if the required argument is {@literal null}. + */ + public UnionWithOperation pipeline(List aggregationStages) { + return new UnionWithOperation(collection, new AggregationPipeline(aggregationStages), domainType); + } + + /** + * Set the aggregation pipeline stages to apply to the specified collection. The pipeline corresponds to the optional + * {@code pipeline} field of the {@code $unionWith} aggregation stage and is used to compute the documents going into + * the result set. + * + * @param aggregationStages the aggregation pipeline stages that compute the documents. Must not be {@literal null}. + * @return new instance of {@link UnionWithOperation}. + * @throws IllegalArgumentException if the required argument is {@literal null}. + */ + public UnionWithOperation pipeline(AggregationOperation... aggregationStages) { + return new UnionWithOperation(collection, new AggregationPipeline(Arrays.asList(aggregationStages)), domainType); + } + + /** + * Set domain type used for field name mapping of property references used by the {@link AggregationPipeline}. + * Remember to also use a {@link TypedAggregation} in the outer pipeline.
      + * If not set, field names used within {@link AggregationOperation pipeline operations} are taken as is. + * + * @param domainType the domain type to map field names used in pipeline operations to. Must not be {@literal null}. + * @return new instance of {@link UnionWithOperation}. + * @throws IllegalArgumentException if the required argument is {@literal null}. + */ + public UnionWithOperation mapFieldsTo(Class domainType) { + + Assert.notNull(domainType, "DomainType must not be null!"); + return new UnionWithOperation(collection, pipeline, domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) + */ + @Override + public Document toDocument(AggregationOperationContext context) { + + Document $unionWith = new Document("coll", collection); + if (pipeline == null || pipeline.isEmpty()) { + return new Document(getOperator(), $unionWith); + } + + $unionWith.append("pipeline", pipeline.toDocuments(computeContext(context))); + return new Document(getOperator(), $unionWith); + } + + private AggregationOperationContext computeContext(AggregationOperationContext source) { + + if (domainType == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + if (source instanceof TypeBasedAggregationOperationContext) { + return ((TypeBasedAggregationOperationContext) source).continueOnMissingFieldReference(domainType); + } + + if (source instanceof ExposedFieldsAggregationOperationContext) { + return computeContext(((ExposedFieldsAggregationOperationContext) source).getRootContext()); + } + + return source; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ + @Override + public String getOperator() { + return "$unionWith"; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java new file mode 100644 index 0000000000..880106bd00 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java @@ -0,0 +1,129 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Arrays; +import java.util.List; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + */ +class UnionWithOperationUnitTests { + + @Test // DATAMONGO-2622 + void throwsErrorWhenNoCollectionPresent() { + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> UnionWithOperation.unionWith(null)); + } + + @Test // DATAMONGO-2622 + void rendersJustCollectionCorrectly() { + + assertThat(UnionWithOperation.unionWith("coll-1").toPipelineStages(contextFor(Warehouse.class))) + .containsExactly(new Document("$unionWith", new Document("coll", "coll-1"))); + } + + @Test // DATAMONGO-2622 + void rendersPipelineCorrectly() { + + assertThat(UnionWithOperation.unionWith("coll-1").mapFieldsTo(Warehouse.class) + .pipeline(Aggregation.project().and("location").as("region")).toPipelineStages(contextFor(Warehouse.class))) + .containsExactly(new Document("$unionWith", new Document("coll", "coll-1").append("pipeline", + Arrays.asList(new Document("$project", new Document("region", 1)))))); + } + + @Test // DATAMONGO-2622 + void rendersPipelineCorrectlyForDifferentDomainType() { + + assertThat(UnionWithOperation.unionWith("coll-1").pipeline(Aggregation.project().and("name").as("name")) + .mapFieldsTo(Supplier.class).toPipelineStages(contextFor(Warehouse.class))) + .containsExactly(new Document("$unionWith", new Document("coll", "coll-1").append("pipeline", + Arrays.asList(new Document("$project", new Document("name", "$supplier")))))); + } + + @Test // DATAMONGO-2622 + void rendersPipelineCorrectlyForUntypedContext() { + + assertThat(UnionWithOperation.unionWith("coll-1").pipeline(Aggregation.project("region")) + .toPipelineStages(contextFor(null))) + .containsExactly(new Document("$unionWith", new Document("coll", "coll-1").append("pipeline", + Arrays.asList(new Document("$project", new Document("region", 1)))))); + } + + @Test // DATAMONGO-2622 + void doesNotMapAgainstFieldsFromAPreviousStage() { + + TypedAggregation agg = TypedAggregation.newAggregation(Supplier.class, + Aggregation.project().and("name").as("supplier"), + UnionWithOperation.unionWith("coll-1").pipeline(Aggregation.project().and("name").as("name"))); + + List pipeline = agg.toPipeline(contextFor(Supplier.class)); + System.out.println("pipeline: " + pipeline); + assertThat(pipeline).containsExactly(new Document("$project", new Document("supplier", 1)), // + new Document("$unionWith", new Document("coll", "coll-1").append("pipeline", + Arrays.asList(new Document("$project", new Document("name", 1)))))); + } + + @Test // DATAMONGO-2622 + void mapAgainstUnionWithDomainTypeEvenWhenInsideTypedAggregation() { + + TypedAggregation agg = TypedAggregation.newAggregation(Supplier.class, + Aggregation.project().and("name").as("supplier"), UnionWithOperation.unionWith("coll-1") + .mapFieldsTo(Warehouse.class).pipeline(Aggregation.project().and("location").as("location"))); + + List pipeline = agg.toPipeline(contextFor(Supplier.class)); + assertThat(pipeline).containsExactly(new Document("$project", new Document("supplier", 1)), // + new Document("$unionWith", new Document("coll", "coll-1").append("pipeline", + Arrays.asList(new Document("$project", new Document("location", "$region")))))); + } + + private static AggregationOperationContext contextFor(@Nullable Class type) { + + if (type == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + MappingMongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, + new MongoMappingContext()); + mongoConverter.afterPropertiesSet(); + + return new TypeBasedAggregationOperationContext(type, mongoConverter.getMappingContext(), + new QueryMapper(mongoConverter)); + } + + static class Warehouse { + + String name; + @Field("region") String location; + String state; + } + + static class Supplier { + + @Field("supplier") String name; + String state; + } +} From 26f0a1c7f909ed97b9844e72da252bab8cc91ca8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 6 Oct 2020 12:08:51 +0200 Subject: [PATCH 0266/1381] DATAMONGO-2622 - Polishing. Rename AggregationPipeline.requiresRelaxedChecking() to containsUnionWith() to avoid the concept of field validation leaking into AggregationPipeline. Refactor AggregationOperation to consistently check their type and fallback to the operator check to allow for consistent checks when using custo AggregationOperations. Original pull request: #886. --- .../data/mongodb/core/AggregationUtil.java | 2 +- .../core/aggregation/AggregationPipeline.java | 54 ++++++++++++------- .../core/aggregation/UnionWithOperation.java | 12 ++--- .../UnionWithOperationUnitTests.java | 2 + 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java index b9c4be1d0d..36fc19a098 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java @@ -82,7 +82,7 @@ AggregationOperationContext prepareAggregationContext(Aggregation aggregation, Class inputType = ((TypedAggregation) aggregation).getInputType(); - if (aggregation.getPipeline().requiresRelaxedChecking()) { + if (aggregation.getPipeline().containsUnionWith()) { return new RelaxedTypeBasedAggregationOperationContext(inputType, mappingContext, queryMapper); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java index 083daa6d81..1421db76a9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; import org.bson.Document; import org.springframework.util.Assert; @@ -26,6 +27,7 @@ * The {@link AggregationPipeline} holds the collection of {@link AggregationOperation aggregation stages}. * * @author Christoph Strobl + * @author Mark Paluch * @since 3.0.2 */ public class AggregationPipeline { @@ -84,42 +86,39 @@ List toDocuments(AggregationOperationContext context) { */ public boolean isOutOrMerge() { - if (pipeline.isEmpty()) { + if (isEmpty()) { return false; } - String operator = pipeline.get(pipeline.size() - 1).getOperator(); - return operator.equals("$out") || operator.equals("$merge"); + AggregationOperation operation = pipeline.get(pipeline.size() - 1); + return isOut(operation) || isMerge(operation); } void verify() { // check $out/$merge is the last operation if it exists - for (AggregationOperation aggregationOperation : pipeline) { + for (AggregationOperation operation : pipeline) { - if (aggregationOperation instanceof OutOperation && !isLast(aggregationOperation)) { + if (isOut(operation) && !isLast(operation)) { throw new IllegalArgumentException("The $out operator must be the last stage in the pipeline."); } - if (aggregationOperation instanceof MergeOperation && !isLast(aggregationOperation)) { + if (isMerge(operation) && !isLast(operation)) { throw new IllegalArgumentException("The $merge operator must be the last stage in the pipeline."); } } } - private boolean isLast(AggregationOperation aggregationOperation) { - return pipeline.indexOf(aggregationOperation) == pipeline.size() - 1; - } - /** - * @return {@literal true} if field names might get computed by one of the pipeline stages, that the - * {@link AggregationOperationContext} might not be aware of. A strongly typed context might fail to resolve - * field references, so if {@literal true} usage of a {@link RelaxedTypeBasedAggregationOperationContext} - * might be the better choice. + * Return whether this aggregation pipeline defines a {@code $unionWith} stage that may contribute documents from + * other collections. Checking for presence of union stages is useful when attempting to determine the aggregation + * element type for mapping metadata computation. + * + * @return {@literal true} the aggregation pipeline makes use of {@code $unionWith}. * @since 3.1 */ - public boolean requiresRelaxedChecking() { - return pipelineContainsValueOfType(UnionWithOperation.class); + public boolean containsUnionWith() { + return containsOperation(AggregationPipeline::isUnionWith); } /** @@ -130,17 +129,34 @@ public boolean isEmpty() { return pipeline.isEmpty(); } - private boolean pipelineContainsValueOfType(Class type) { + private boolean containsOperation(Predicate predicate) { if (isEmpty()) { return false; } - for (Object element : pipeline) { - if (type.isInstance(element)) { + for (AggregationOperation element : pipeline) { + if (predicate.test(element)) { return true; } } + return false; } + + private boolean isLast(AggregationOperation aggregationOperation) { + return pipeline.indexOf(aggregationOperation) == pipeline.size() - 1; + } + + private static boolean isUnionWith(AggregationOperation operator) { + return operator instanceof UnionWithOperation || operator.getOperator().equals("$unionWith"); + } + + private static boolean isMerge(AggregationOperation operator) { + return operator instanceof MergeOperation || operator.getOperator().equals("$merge"); + } + + private static boolean isOut(AggregationOperation operator) { + return operator instanceof OutOperation || operator.getOperator().equals("$out"); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java index c30e8c7ec1..8bbb730b3d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java @@ -45,14 +45,14 @@ public class UnionWithOperation implements AggregationOperation { private final String collection; - @Nullable // - private final AggregationPipeline pipeline; + private final @Nullable AggregationPipeline pipeline; - @Nullable // - private final Class domainType; + private final @Nullable Class domainType; public UnionWithOperation(String collection, @Nullable AggregationPipeline pipeline, @Nullable Class domainType) { + Assert.notNull(collection, "Collection must not be null!"); + this.collection = collection; this.pipeline = pipeline; this.domainType = domainType; @@ -67,8 +67,6 @@ public UnionWithOperation(String collection, @Nullable AggregationPipeline pipel * @throws IllegalArgumentException if the required argument is {@literal null}. */ public static UnionWithOperation unionWith(String collection) { - - Assert.notNull(collection, "Collection must not be null!"); return new UnionWithOperation(collection, null, null); } @@ -76,7 +74,7 @@ public static UnionWithOperation unionWith(String collection) { * Set the {@link AggregationPipeline} to apply to the specified collection. The pipeline corresponds to the optional * {@code pipeline} field of the {@code $unionWith} aggregation stage and is used to compute the documents going into * the result set. - * + * * @param pipeline the {@link AggregationPipeline} that computes the documents. Must not be {@literal null}. * @return new instance of {@link UnionWithOperation}. * @throws IllegalArgumentException if the required argument is {@literal null}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java index 880106bd00..1611d3c21d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperationUnitTests.java @@ -30,6 +30,8 @@ import org.springframework.lang.Nullable; /** + * Unit tests for {@link UnionWithOperation}. + * * @author Christoph Strobl */ class UnionWithOperationUnitTests { From 0ef852a8fcdb4654d8242b568f12e52f92575ada Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 25 Sep 2020 13:31:16 +0200 Subject: [PATCH 0267/1381] DATAMONGO-2623 - Add support for $function and $accumulator aggregation operators. Original pull request: #887. --- .../AbstractAggregationExpression.java | 42 ++ .../core/aggregation/ScriptOperators.java | 548 ++++++++++++++++++ .../aggregation/ScriptOperatorsUnitTests.java | 94 +++ src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/reference/mongodb.adoc | 4 + 5 files changed, 689 insertions(+) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java index ad607cbcae..82c03758b4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java @@ -140,6 +140,48 @@ protected java.util.Map append(String key, Object value) { } + protected java.util.Map remove(String key) { + + Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); + + java.util.Map clone = new LinkedHashMap<>((java.util.Map) this.value); + clone.remove(key); + return clone; + } + + /** + * Append the given key at the position in the underlying {@link LinkedHashMap}. + * + * @param index + * @param key + * @param value + * @return + * @since 3.1 + */ + protected java.util.Map appendAt(int index, String key, Object value) { + + Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); + + java.util.LinkedHashMap clone = new java.util.LinkedHashMap<>(); + + int i = 0; + for (Map.Entry entry : ((java.util.Map) this.value).entrySet()) { + + if (i == index) { + clone.put(key, value); + } + if (!entry.getKey().equals(key)) { + clone.put(entry.getKey(), entry.getValue()); + } + i++; + } + if (i <= index) { + clone.put(key, value); + } + return clone; + + } + protected List values() { if (value instanceof List) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java new file mode 100644 index 0000000000..6d451aca0a --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java @@ -0,0 +1,548 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorBuilder; +import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorInitBuilder; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * Gateway to {@literal $function} and {@literal $accumulator} aggregation operations. + *

      + * Using {@link ScriptOperators} as part of the {@link Aggregation} requires MongoDB server to have + * server-side JavaScript execution + * enabled. + * + * @author Christoph Strobl + * @since 3.1 + */ +public class ScriptOperators { + + /** + * Create a custom aggregation + * $function in JavaScript. + * + * @param body The function definition. Must not be {@literal null}. + * @return new instance of {@link Function}. + */ + public static Function function(String body) { + return Function.function(body); + } + + /** + * Create a custom $accumulator + * operator in Javascript. + * + * @return new instance of {@link AccumulatorInitBuilder}. + */ + public static AccumulatorInitBuilder accumulatorBuilder() { + return new AccumulatorBuilder(); + } + + /** + * {@link Function} defines a custom aggregation + * $function in JavaScript. + *

      + * + * { + * $function: { + * body: ..., + * args: ..., + * lang: "js" + * } + * } + * + *

      + * {@link Function} cannot be used as part of {@link org.springframework.data.mongodb.core.schema.MongoJsonSchema + * schema} validation query expression.
      + * NOTE: Server-Side JavaScript + * execution must be + * enabled + * + * @see MongoDB Documentation: + * $function + * @since 3.1 + */ + public static class Function extends AbstractAggregationExpression { + + private Function(Map values) { + super(values); + } + + /** + * Create a new {@link Function} with the given function definition. + * + * @param body must not be {@literal null}. + * @return new instance of {@link Function}. + */ + public static Function function(String body) { + + Map function = new LinkedHashMap<>(2); + function.put(Fields.BODY.toString(), body); + function.put(Fields.ARGS.toString(), Collections.emptyList()); + function.put(Fields.LANG.toString(), "js"); + + return new Function(function); + } + + /** + * Set the arguments passed to the function body. + * + * @param args the arguments passed to the function body. Leave empty if the function does not take any arguments. + * @return new instance of {@link Function}. + */ + public Function args(Object... args) { + return args(Arrays.asList(args)); + } + + /** + * Set the arguments passed to the function body. + * + * @param args the arguments passed to the function body. Leave empty if the function does not take any arguments. + * @return new instance of {@link Function}. + */ + public Function args(List args) { + + Assert.notNull(args, "Args must not be null! Use an empty list instead."); + return new Function(appendAt(1, Fields.ARGS.toString(), args)); + } + + /** + * The language used in the body. + * + * @param lang must not be {@literal null} nor empty. + * @return new instance of {@link Function}. + */ + public Function lang(String lang) { + + Assert.hasText(lang, "Lang must not be null nor emtpy! The default would be 'js'."); + return new Function(appendAt(2, Fields.LANG.toString(), lang)); + } + + @Nullable + List getArgs() { + return get(Fields.ARGS.toString()); + } + + String getBody() { + return get(Fields.BODY.toString()); + } + + String getLang() { + return get(Fields.LANG.toString()); + } + + @Override + protected String getMongoMethod() { + return "$function"; + } + + enum Fields { + + BODY, ARGS, LANG; + + @Override + public String toString() { + return name().toLowerCase(); + } + } + } + + /** + * {@link Accumulator} defines a custom aggregation + * $accumulator operator, + * one that maintains its state (e.g. totals, maximums, minimums, and related data) as documents progress through the + * pipeline, in JavaScript. + *

      + * + * { + * $accumulator: { + * init: ..., + * intArgs: ..., + * accumulate: ..., + * accumulateArgs: ..., + * merge: ..., + * finalize: ..., + * lang: "js" + * } + * } + * + *

      + * {@link Accumulator} can be used as part of {@link GroupOperation $group}, {@link BucketOperation $bucket} and + * {@link BucketAutoOperation $bucketAuto} pipeline stages.
      + * NOTE: Server-Side JavaScript + * execution must be + * enabled + * + * @see MongoDB Documentation: + * $accumulator + * @since 3.1 + */ + public static class Accumulator extends AbstractAggregationExpression { + + private Accumulator(Map value) { + super(value); + } + + @Override + protected String getMongoMethod() { + return "$accumulator"; + } + + enum Fields { + + ACCUMULATE("accumulate"), // + ACCUMULATE_ARGS("accumulateArgs"), // + FINALIZE("finalize"), // + INIT("init"), // + INIT_ARGS("initArgs"), // + LANG("lang"), // + MERGE("merge"); // + + private String field; + + Fields(String field) { + this.field = field; + } + + @Override + public String toString() { + return field; + } + } + + public interface AccumulatorInitBuilder { + + /** + * Define the {@code init} {@link Function} for the {@link Accumulator accumulators} initial state. The function + * receives its arguments from the {@link Function#args(Object...) initArgs} array expression. + *

      + * + * function(initArg1, initArg2, ...) { + * ... + * return initialState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + default AccumulatorAccumulateBuilder init(Function function) { + return init(function.getBody()).initArgs(function.getArgs()); + } + + /** + * Define the {@code init} function for the {@link Accumulator accumulators} initial state. The function receives + * its arguments from the {@link AccumulatorInitArgsBuilder#initArgs(Object...)} array expression. + *

      + * + * function(initArg1, initArg2, ...) { + * ... + * return initialState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + AccumulatorInitArgsBuilder init(String function); + + /** + * The language used in the {@code $accumulator} code. + * + * @param lang must not be {@literal null}. Default is {@literal js}. + * @return this. + */ + AccumulatorInitBuilder lang(String lang); + } + + public interface AccumulatorInitArgsBuilder extends AccumulatorAccumulateBuilder { + + /** + * Define the optional {@code initArgs} for the {@link AccumulatorInitBuilder#init(String)} function. + * + * @param args must not be {@literal null}. + * @return this. + */ + default AccumulatorAccumulateBuilder initArgs(Object... args) { + return initArgs(Arrays.asList(args)); + } + + /** + * Define the optional {@code initArgs} for the {@link AccumulatorInitBuilder#init(String)} function. + * + * @param args can be {@literal null}. + * @return this. + */ + AccumulatorAccumulateBuilder initArgs(@Nullable List args); + } + + public interface AccumulatorAccumulateBuilder { + + /** + * Set the {@code accumulate} {@link Function} that updates the state for each document. The functions first + * argument is the current {@code state}, additional arguments can be defined via {@link Function#args(Object...) + * accumulateArgs}. + *

      + * + * function(state, accumArg1, accumArg2, ...) { + * ... + * return newState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + default AccumulatorMergeBuilder accumulate(Function function) { + return accumulate(function.getBody()).accumulateArgs(function.getArgs()); + } + + /** + * Set the {@code accumulate} function that updates the state for each document. The functions first argument is + * the current {@code state}, additional arguments can be defined via + * {@link AccumulatorAccumulateArgsBuilder#accumulateArgs(Object...)}. + *

      + * + * function(state, accumArg1, accumArg2, ...) { + * ... + * return newState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + AccumulatorAccumulateArgsBuilder accumulate(String function); + } + + public interface AccumulatorAccumulateArgsBuilder extends AccumulatorMergeBuilder { + + /** + * Define additional {@code accumulateArgs} for the {@link AccumulatorAccumulateBuilder#accumulate(String)} + * function. + * + * @param args must not be {@literal null}. + * @return this. + */ + default AccumulatorMergeBuilder accumulateArgs(Object... args) { + return accumulateArgs(Arrays.asList(args)); + } + + /** + * Define additional {@code accumulateArgs} for the {@link AccumulatorAccumulateBuilder#accumulate(String)} + * function. + * + * @param args can be {@literal null}. + * @return this. + */ + AccumulatorMergeBuilder accumulateArgs(@Nullable List args); + } + + public interface AccumulatorMergeBuilder { + + /** + * Set the {@code merge} function used to merge two internal states.
      + * This might be required because the operation is run on a sharded cluster or when the operator exceeds its + * memory limit. + *

      + * + * function(state1, state2) { + * ... + * return newState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + AccumulatorFinalizeBuilder merge(String function); + } + + public interface AccumulatorFinalizeBuilder { + + /** + * Set the {@code finalize} function used to update the result of the accumulation when all documents have been + * processed. + *

      + * + * function(state) { + * ... + * return finalState + * } + * + * + * @param function must not be {@literal null}. + * @return new instance of {@link Accumulator}. + */ + Accumulator finalize(String function); + } + + public static class AccumulatorBuilder + implements AccumulatorInitBuilder, AccumulatorInitArgsBuilder, AccumulatorAccumulateBuilder, + AccumulatorAccumulateArgsBuilder, AccumulatorMergeBuilder, AccumulatorFinalizeBuilder { + + private List initArgs; + private String initFunction; + private List accumulateArgs; + private String accumulateFunction; + private String mergeFunction; + private String finalizeFunction; + private String lang = "js"; + + /** + * Define the {@code init} function for the {@link Accumulator accumulators} initial state. The function receives + * its arguments from the {@link #initArgs(Object...)} array expression. + *

      + * + * function(initArg1, initArg2, ...) { + * ... + * return initialState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + public AccumulatorBuilder init(String function) { + + this.initFunction = function; + return this; + } + + /** + * Define the optional {@code initArgs} for the {@link #init(String)} function. + * + * @param args can be {@literal null}. + * @return this. + */ + public AccumulatorBuilder initArgs(@Nullable List args) { + + this.initArgs = args != null ? new ArrayList<>(args) : Collections.emptyList(); + return this; + } + + /** + * Set the {@code accumulate} function that updates the state for each document. The functions first argument is + * the current {@code state}, additional arguments can be defined via {@link #accumulateArgs(Object...)}. + *

      + * + * function(state, accumArg1, accumArg2, ...) { + * ... + * return newState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + public AccumulatorBuilder accumulate(String function) { + + this.accumulateFunction = function; + return this; + } + + /** + * Define additional {@code accumulateArgs} for the {@link #accumulate(String)} function. + * + * @param args can be {@literal null}. + * @return this. + */ + public AccumulatorBuilder accumulateArgs(@Nullable List args) { + + this.accumulateArgs = args != null ? new ArrayList<>(args) : Collections.emptyList(); + return this; + } + + /** + * Set the {@code merge} function used to merge two internal states.
      + * This might be required because the operation is run on a sharded cluster or when the operator exceeds its + * memory limit. + *

      + * + * function(state1, state2) { + * ... + * return newState + * } + * + * + * @param function must not be {@literal null}. + * @return this. + */ + public AccumulatorBuilder merge(String function) { + + this.mergeFunction = function; + return this; + } + + /** + * The language used in the {@code $accumulator} code. + * + * @param lang must not be {@literal null}. Default is {@literal js}. + * @return this. + */ + public AccumulatorBuilder lang(String lang) { + + this.lang = lang; + return this; + } + + /** + * Set the {@code finalize} function used to update the result of the accumulation when all documents have been + * processed. + *

      + * + * function(state) { + * ... + * return finalState + * } + * + * + * @param function must not be {@literal null}. + * @return new instance of {@link Accumulator}. + */ + public Accumulator finalize(String function) { + + this.finalizeFunction = function; + + Map args = new LinkedHashMap<>(); + args.put(Fields.INIT.toString(), initFunction); + if (!CollectionUtils.isEmpty(initArgs)) { + args.put(Fields.INIT_ARGS.toString(), initArgs); + } + args.put(Fields.ACCUMULATE.toString(), accumulateFunction); + if (!CollectionUtils.isEmpty(accumulateArgs)) { + args.put(Fields.ACCUMULATE_ARGS.toString(), accumulateArgs); + } + args.put(Fields.MERGE.toString(), mergeFunction); + args.put(Fields.FINALIZE.toString(), finalizeFunction); + args.put(Fields.LANG.toString(), lang); + + return new Accumulator(args); + } + + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java new file mode 100644 index 0000000000..fb237b6315 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java @@ -0,0 +1,94 @@ +/* + * Copyright 2020 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.aggregation.ScriptOperators.*; + +import java.util.Collections; + +import org.bson.Document; +import org.junit.jupiter.api.Test; + +/** + * @author Christoph Strobl + */ +class ScriptOperatorsUnitTests { + + private static final String FUNCTION_BODY = "function(name) { return hex_md5(name) == \"15b0a220baa16331e8d80e15367677ad\" }"; + private static final Document EMPTY_ARGS_FUNCTION_DOCUMENT = new Document("body", FUNCTION_BODY) + .append("args", Collections.emptyList()).append("lang", "js"); + + @Test // DATAMONGO-2623 + void functionWithoutArgsShouldBeRenderedCorrectly() { + + assertThat(function(FUNCTION_BODY).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo($function(EMPTY_ARGS_FUNCTION_DOCUMENT)); + } + + @Test // DATAMONGO-2623 + void functionWithArgsShouldBeRenderedCorrectly() { + + assertThat(function(FUNCTION_BODY).args("$name").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( + $function(new Document(EMPTY_ARGS_FUNCTION_DOCUMENT).append("args", Collections.singletonList("$name")))); + } + + private static final String INIT_FUNCTION = "function() { return { count: 0, sum: 0 } }"; + private static final String ACC_FUNCTION = "function(state, numCopies) { return { count: state.count + 1, sum: state.sum + numCopies } }"; + private static final String MERGE_FUNCTION = "function(state1, state2) { return { count: state1.count + state2.count, sum: state1.sum + state2.sum } }"; + private static final String FINALIZE_FUNCTION = "function(state) { return (state.sum / state.count) }"; + + private static final Document $ACCUMULATOR = Document.parse("{" + // + " $accumulator:" + // + " {" + // + " init: '" + INIT_FUNCTION + "'," + // + " accumulate: '" + ACC_FUNCTION + "'," + // + " accumulateArgs: [\"$copies\"]," + // + " merge: '" + MERGE_FUNCTION + "'," + // + " finalize: '" + FINALIZE_FUNCTION + "'," + // + " lang: \"js\"" + // + " }" + // + " }" + // + " }"); + + @Test // DATAMONGO-2623 + void accumulatorWithStringInput() { + + Accumulator accumulator = accumulatorBuilder() // + .init(INIT_FUNCTION) // + .accumulate(ACC_FUNCTION).accumulateArgs("$copies") // + .merge(MERGE_FUNCTION) // + .finalize(FINALIZE_FUNCTION); + + assertThat(accumulator.toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo($ACCUMULATOR); + } + + @Test // DATAMONGO-2623 + void accumulatorWithFunctionInput() { + + Accumulator accumulator = accumulatorBuilder() // + .init(function(INIT_FUNCTION)) // + .accumulate(function(ACC_FUNCTION).args("$copies")) // + .merge(MERGE_FUNCTION) // + .finalize(FINALIZE_FUNCTION); + + assertThat(accumulator.toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo($ACCUMULATOR); + } + + static Document $function(Document source) { + return new Document("$function", source); + } +} diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 071d56f32b..305e349cdd 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -8,6 +8,7 @@ * Reactive SpEL support in `@Query` and `@Aggregation` query methods. * Aggregation hints via `AggregationOptions.builder().hint(bson).build()`. * Extension Function `KProperty.asPath()` to render property references into a property path representation. +* Server-side JavaScript aggregation expressions `$function` and `$accumulator` via `ScriptOperators`. [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 75ad097ce9..7c6395fc56 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2559,6 +2559,7 @@ The MongoDB Aggregation Framework provides the following types of aggregation op * Lookup Aggregation Operators * Convert Aggregation Operators * Object Aggregation Operators +* Script Aggregation Operators At the time of this writing, we provide support for the following Aggregation Operations in Spring Data MongoDB: @@ -2606,6 +2607,9 @@ At the time of this writing, we provide support for the following Aggregation Op | Object Aggregation Operators | `objectToArray`, `mergeObjects` + +| Script Aggregation Operators +| `function`, `accumulator` |=== * The operation is mapped or added by Spring Data MongoDB. From 217be64a77f8999891dabaa7aef1d2ccf7f524e6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 7 Oct 2020 09:50:23 +0200 Subject: [PATCH 0268/1381] DATAMONGO-2623 - Polishing. Avoid nullable method arguments and add assertions. Introduce build() method to AccumulatorFinalizeBuilder to build Accumulator without specifying a finalize function. Original pull request: #887. --- .../AbstractAggregationExpression.java | 37 ++++++---- .../core/aggregation/ScriptOperators.java | 73 ++++++++++++++----- .../aggregation/ScriptOperatorsUnitTests.java | 30 ++++---- 3 files changed, 95 insertions(+), 45 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java index 82c03758b4..07fa9023cc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AbstractAggregationExpression.java @@ -29,8 +29,11 @@ import org.springframework.util.ObjectUtils; /** + * Support class for {@link AggregationExpression} implementations. + * * @author Christoph Strobl * @author Matt Morrissette + * @author Mark Paluch * @since 1.10 */ abstract class AbstractAggregationExpression implements AggregationExpression { @@ -49,7 +52,6 @@ public Document toDocument(AggregationOperationContext context) { return toDocument(this.value, context); } - @SuppressWarnings("unchecked") public Document toDocument(Object value, AggregationOperationContext context) { return new Document(getMongoMethod(), unpack(value, context)); } @@ -101,17 +103,19 @@ private Object unpack(Object value, AggregationOperationContext context) { return value; } + @SuppressWarnings("unchecked") protected List append(Object value, Expand expandList) { if (this.value instanceof List) { - List clone = new ArrayList((List) this.value); + List clone = new ArrayList<>((List) this.value); if (value instanceof Collection && Expand.EXPAND_VALUES.equals(expandList)) { clone.addAll((Collection) value); } else { clone.add(value); } + return clone; } @@ -129,22 +133,23 @@ protected List append(Object value) { return append(value, Expand.EXPAND_VALUES); } - @SuppressWarnings("unchecked") - protected java.util.Map append(String key, Object value) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Map append(String key, Object value) { Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); - java.util.Map clone = new LinkedHashMap<>((java.util.Map) this.value); + Map clone = new LinkedHashMap<>((java.util.Map) this.value); clone.put(key, value); return clone; } - protected java.util.Map remove(String key) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Map remove(String key) { Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); - java.util.Map clone = new LinkedHashMap<>((java.util.Map) this.value); + Map clone = new LinkedHashMap<>((java.util.Map) this.value); clone.remove(key); return clone; } @@ -158,14 +163,15 @@ protected java.util.Map remove(String key) { * @return * @since 3.1 */ - protected java.util.Map appendAt(int index, String key, Object value) { + @SuppressWarnings({ "unchecked" }) + protected Map appendAt(int index, String key, Object value) { Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); - java.util.LinkedHashMap clone = new java.util.LinkedHashMap<>(); + Map clone = new LinkedHashMap<>(); int i = 0; - for (Map.Entry entry : ((java.util.Map) this.value).entrySet()) { + for (Map.Entry entry : ((Map) this.value).entrySet()) { if (i == index) { clone.put(key, value); @@ -182,14 +188,17 @@ protected java.util.Map appendAt(int index, String key, Object v } + @SuppressWarnings({ "rawtypes" }) protected List values() { if (value instanceof List) { return new ArrayList((List) value); } + if (value instanceof java.util.Map) { return new ArrayList(((java.util.Map) value).values()); } + return new ArrayList<>(Collections.singletonList(value)); } @@ -219,7 +228,7 @@ protected T get(Object key) { Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); - return (T) ((java.util.Map) this.value).get(key); + return (T) ((Map) this.value).get(key); } /** @@ -229,11 +238,11 @@ protected T get(Object key) { * @return */ @SuppressWarnings("unchecked") - protected java.util.Map argumentMap() { + protected Map argumentMap() { Assert.isInstanceOf(Map.class, this.value, "Value must be a type of Map!"); - return Collections.unmodifiableMap((java.util.Map) value); + return Collections.unmodifiableMap((java.util.Map) value); } /** @@ -250,7 +259,7 @@ protected boolean contains(Object key) { return false; } - return ((java.util.Map) this.value).containsKey(key); + return ((Map) this.value).containsKey(key); } protected abstract String getMongoMethod(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java index 6d451aca0a..3fde9da6a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java @@ -36,6 +36,7 @@ * enabled. * * @author Christoph Strobl + * @author Mark Paluch * @since 3.1 */ public class ScriptOperators { @@ -83,7 +84,6 @@ public static AccumulatorInitBuilder accumulatorBuilder() { * * @see MongoDB Documentation: * $function - * @since 3.1 */ public static class Function extends AbstractAggregationExpression { @@ -99,6 +99,8 @@ private Function(Map values) { */ public static Function function(String body) { + Assert.notNull(body, "Function body must not be null!"); + Map function = new LinkedHashMap<>(2); function.put(Fields.BODY.toString(), body); function.put(Fields.ARGS.toString(), Collections.emptyList()); @@ -126,6 +128,7 @@ public Function args(Object... args) { public Function args(List args) { Assert.notNull(args, "Args must not be null! Use an empty list instead."); + return new Function(appendAt(1, Fields.ARGS.toString(), args)); } @@ -137,7 +140,8 @@ public Function args(List args) { */ public Function lang(String lang) { - Assert.hasText(lang, "Lang must not be null nor emtpy! The default would be 'js'."); + Assert.hasText(lang, "Lang must not be null nor empty! The default would be 'js'."); + return new Function(appendAt(2, Fields.LANG.toString(), lang)); } @@ -198,7 +202,6 @@ public String toString() { * * @see MongoDB Documentation: * $accumulator - * @since 3.1 */ public static class Accumulator extends AbstractAggregationExpression { @@ -293,10 +296,10 @@ default AccumulatorAccumulateBuilder initArgs(Object... args) { /** * Define the optional {@code initArgs} for the {@link AccumulatorInitBuilder#init(String)} function. * - * @param args can be {@literal null}. + * @param args must not be {@literal null}. * @return this. */ - AccumulatorAccumulateBuilder initArgs(@Nullable List args); + AccumulatorAccumulateBuilder initArgs(List args); } public interface AccumulatorAccumulateBuilder { @@ -355,10 +358,10 @@ default AccumulatorMergeBuilder accumulateArgs(Object... args) { * Define additional {@code accumulateArgs} for the {@link AccumulatorAccumulateBuilder#accumulate(String)} * function. * - * @param args can be {@literal null}. + * @param args must not be {@literal null}. * @return this. */ - AccumulatorMergeBuilder accumulateArgs(@Nullable List args); + AccumulatorMergeBuilder accumulateArgs(List args); } public interface AccumulatorMergeBuilder { @@ -398,9 +401,16 @@ public interface AccumulatorFinalizeBuilder { * @return new instance of {@link Accumulator}. */ Accumulator finalize(String function); + + /** + * Build the {@link Accumulator} object without specifying a {@link #finalize(String) finalize function}. + * + * @return new instance of {@link Accumulator}. + */ + Accumulator build(); } - public static class AccumulatorBuilder + static class AccumulatorBuilder implements AccumulatorInitBuilder, AccumulatorInitArgsBuilder, AccumulatorAccumulateBuilder, AccumulatorAccumulateArgsBuilder, AccumulatorMergeBuilder, AccumulatorFinalizeBuilder { @@ -426,6 +436,7 @@ public static class AccumulatorBuilder * @param function must not be {@literal null}. * @return this. */ + @Override public AccumulatorBuilder init(String function) { this.initFunction = function; @@ -435,12 +446,15 @@ public AccumulatorBuilder init(String function) { /** * Define the optional {@code initArgs} for the {@link #init(String)} function. * - * @param args can be {@literal null}. + * @param function must not be {@literal null}. * @return this. */ - public AccumulatorBuilder initArgs(@Nullable List args) { + @Override + public AccumulatorBuilder initArgs(List args) { + + Assert.notNull(args, "Args must not be null"); - this.initArgs = args != null ? new ArrayList<>(args) : Collections.emptyList(); + this.initArgs = new ArrayList<>(args); return this; } @@ -458,8 +472,11 @@ public AccumulatorBuilder initArgs(@Nullable List args) { * @param function must not be {@literal null}. * @return this. */ + @Override public AccumulatorBuilder accumulate(String function) { + Assert.notNull(function, "Accumulate function must not be null"); + this.accumulateFunction = function; return this; } @@ -467,12 +484,15 @@ public AccumulatorBuilder accumulate(String function) { /** * Define additional {@code accumulateArgs} for the {@link #accumulate(String)} function. * - * @param args can be {@literal null}. + * @param args must not be {@literal null}. * @return this. */ - public AccumulatorBuilder accumulateArgs(@Nullable List args) { + @Override + public AccumulatorBuilder accumulateArgs(List args) { - this.accumulateArgs = args != null ? new ArrayList<>(args) : Collections.emptyList(); + Assert.notNull(args, "Args must not be null"); + + this.accumulateArgs = new ArrayList<>(args); return this; } @@ -491,8 +511,11 @@ public AccumulatorBuilder accumulateArgs(@Nullable List args) { * @param function must not be {@literal null}. * @return this. */ + @Override public AccumulatorBuilder merge(String function) { + Assert.notNull(function, "Merge function must not be null"); + this.mergeFunction = function; return this; } @@ -505,6 +528,8 @@ public AccumulatorBuilder merge(String function) { */ public AccumulatorBuilder lang(String lang) { + Assert.hasText(lang, "Lang must not be null nor empty! The default would be 'js'."); + this.lang = lang; return this; } @@ -523,10 +548,26 @@ public AccumulatorBuilder lang(String lang) { * @param function must not be {@literal null}. * @return new instance of {@link Accumulator}. */ + @Override public Accumulator finalize(String function) { + Assert.notNull(function, "Finalize function must not be null"); + this.finalizeFunction = function; + Map args = createArgumentMap(); + args.put(Fields.FINALIZE.toString(), finalizeFunction); + + return new Accumulator(args); + } + + @Override + public Accumulator build() { + return new Accumulator(createArgumentMap()); + } + + private Map createArgumentMap() { + Map args = new LinkedHashMap<>(); args.put(Fields.INIT.toString(), initFunction); if (!CollectionUtils.isEmpty(initArgs)) { @@ -537,12 +578,10 @@ public Accumulator finalize(String function) { args.put(Fields.ACCUMULATE_ARGS.toString(), accumulateArgs); } args.put(Fields.MERGE.toString(), mergeFunction); - args.put(Fields.FINALIZE.toString(), finalizeFunction); args.put(Fields.LANG.toString(), lang); - return new Accumulator(args); + return args; } - } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java index fb237b6315..3e9d9e8041 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ScriptOperatorsUnitTests.java @@ -24,6 +24,8 @@ import org.junit.jupiter.api.Test; /** + * Unit tests for {@link ScriptOperators}. + * * @author Christoph Strobl */ class ScriptOperatorsUnitTests { @@ -32,20 +34,6 @@ class ScriptOperatorsUnitTests { private static final Document EMPTY_ARGS_FUNCTION_DOCUMENT = new Document("body", FUNCTION_BODY) .append("args", Collections.emptyList()).append("lang", "js"); - @Test // DATAMONGO-2623 - void functionWithoutArgsShouldBeRenderedCorrectly() { - - assertThat(function(FUNCTION_BODY).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo($function(EMPTY_ARGS_FUNCTION_DOCUMENT)); - } - - @Test // DATAMONGO-2623 - void functionWithArgsShouldBeRenderedCorrectly() { - - assertThat(function(FUNCTION_BODY).args("$name").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( - $function(new Document(EMPTY_ARGS_FUNCTION_DOCUMENT).append("args", Collections.singletonList("$name")))); - } - private static final String INIT_FUNCTION = "function() { return { count: 0, sum: 0 } }"; private static final String ACC_FUNCTION = "function(state, numCopies) { return { count: state.count + 1, sum: state.sum + numCopies } }"; private static final String MERGE_FUNCTION = "function(state1, state2) { return { count: state1.count + state2.count, sum: state1.sum + state2.sum } }"; @@ -64,6 +52,20 @@ void functionWithArgsShouldBeRenderedCorrectly() { " }" + // " }"); + @Test // DATAMONGO-2623 + void functionWithoutArgsShouldBeRenderedCorrectly() { + + assertThat(function(FUNCTION_BODY).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo($function(EMPTY_ARGS_FUNCTION_DOCUMENT)); + } + + @Test // DATAMONGO-2623 + void functionWithArgsShouldBeRenderedCorrectly() { + + assertThat(function(FUNCTION_BODY).args("$name").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( + $function(new Document(EMPTY_ARGS_FUNCTION_DOCUMENT).append("args", Collections.singletonList("$name")))); + } + @Test // DATAMONGO-2623 void accumulatorWithStringInput() { From aaa45578875e7192291433718b8841be06d122cc Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 1 Sep 2020 10:26:06 +0200 Subject: [PATCH 0269/1381] DATAMONGO-2616 - Short circuit id value assignment in MongoConverter. Original pull request: #889. --- .../data/mongodb/core/convert/MongoConverter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index c5e447c9cc..8358e84e67 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -131,6 +131,10 @@ default Object convertId(@Nullable Object id, Class targetType) { return null; } + if(ClassUtils.isAssignableValue(targetType, id)) { + return id; + } + if (ClassUtils.isAssignable(ObjectId.class, targetType)) { if (id instanceof String) { From 9af8a732900502555bb5a5a6eceef4de601d62c5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 7 Oct 2020 11:35:31 +0200 Subject: [PATCH 0270/1381] DATAMONGO-2616 - Polishing. Reformat code. Merge if-statements. Original pull request: #889. --- .../data/mongodb/core/convert/MongoConverter.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index 8358e84e67..5086f30401 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -127,11 +127,7 @@ default T mapValueToTargetType(S source, Class targetType, DbRefResolv @Nullable default Object convertId(@Nullable Object id, Class targetType) { - if (id == null) { - return null; - } - - if(ClassUtils.isAssignableValue(targetType, id)) { + if (id == null || ClassUtils.isAssignableValue(targetType, id)) { return id; } From ad77f2336451311bc29691cad91ed9c974f2ee81 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 14 Oct 2020 14:27:30 +0200 Subject: [PATCH 0271/1381] DATAMONGO-2626 - Updated changelog. --- src/main/resources/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 2677a17a2a..c012660afc 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,17 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.0-RC2 (2020-10-14) +----------------------------------------- +* DATAMONGO-2633 - @Query annotation does not support $centerSphere. +* DATAMONGO-2630 - Add support for suspend repository query methods returning List. +* DATAMONGO-2626 - Release 3.1 RC2 (2020.0.0). +* DATAMONGO-2623 - Add support for custom Aggregation expressions. +* DATAMONGO-2622 - Add support for $unionWith aggregation. +* DATAMONGO-2596 - Introduce extension to render KProperty/KPropertyPath as property path. +* DATAMONGO-2294 - Support multiple parameters for query field projections. + + Changes in version 3.1.0-RC1 (2020-09-16) ----------------------------------------- * DATAMONGO-2621 - Adapt to changed array assertions in AssertJ. @@ -3173,5 +3184,6 @@ Repository + From 20f702512bd9205129dea824041acfbe96d9154b Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 14 Oct 2020 14:27:37 +0200 Subject: [PATCH 0272/1381] DATAMONGO-2626 - Prepare 3.1 RC2 (2020.0.0). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9d352e7658..5fb4174c8c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-SNAPSHOT + 2.4.0-RC2 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-SNAPSHOT + 2.4.0-RC2 4.1.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index ecfc557c9b..a806d94ce2 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.1 RC1 (2020.0.0) +Spring Data MongoDB 3.1 RC2 (2020.0.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -18,3 +18,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 2c6e645a3db25b240bfaf7845b5e707e4320200e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 14 Oct 2020 14:28:55 +0200 Subject: [PATCH 0273/1381] DATAMONGO-2626 - Release version 3.1 RC2 (2020.0.0). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 5fb4174c8c..ad6b8a58b9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC2 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a85b081e26..3be2c57ff0 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC2 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 33014c7c4f..8e7fd4486f 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC2 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ea401d5618..3036b2fb55 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-RC2 ../pom.xml From 05fc6546ff412b0cb9825a5610c5b01f5ed562ef Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 14 Oct 2020 14:48:45 +0200 Subject: [PATCH 0274/1381] DATAMONGO-2626 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ad6b8a58b9..5fb4174c8c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC2 + 3.1.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 3be2c57ff0..a85b081e26 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC2 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 8e7fd4486f..33014c7c4f 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC2 + 3.1.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 3036b2fb55..ea401d5618 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-RC2 + 3.1.0-SNAPSHOT ../pom.xml From 5aa29fc7b81e4696d11fb494f57d03d78e23b3b5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 14 Oct 2020 14:48:47 +0200 Subject: [PATCH 0275/1381] DATAMONGO-2626 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 5fb4174c8c..9d352e7658 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-RC2 + 2.4.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-RC2 + 2.4.0-SNAPSHOT 4.1.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From bbbe3690934ef1cf234628793e502ed321d03ee5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 26 Oct 2020 12:46:07 +0100 Subject: [PATCH 0276/1381] DATAMONGO-2642 - Upgrade MongoDB drivers to 4.1.1. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9d352e7658..b0509f1c29 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.4.0-SNAPSHOT - 4.1.0 + 4.1.1 ${mongo} 1.19 From 2d348be5b2bb8be6f6826cf4e7b7838d4a7e8967 Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Mon, 26 Oct 2020 13:26:11 -0500 Subject: [PATCH 0277/1381] DATAMONGO-2629 - Use JDK 15 for next CI jobs. --- Jenkinsfile | 10 +++++----- .../Dockerfile | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename ci/{openjdk14-mongodb-4.2 => openjdk15-mongodb-4.2}/Dockerfile (94%) diff --git a/Jenkinsfile b/Jenkinsfile index 16a4d35925..4f1379af27 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,16 +46,16 @@ pipeline { } } } - stage('Publish JDK 14 + MongoDB 4.2') { + stage('Publish JDK 15 + MongoDB 4.2') { when { - changeset "ci/openjdk14-mongodb-4.2/**" + changeset "ci/openjdk15-mongodb-4.2/**" } agent { label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { script { - def image = docker.build("springci/spring-data-openjdk14-with-mongodb-4.2.0", "ci/openjdk14-mongodb-4.2/") + def image = docker.build("springci/spring-data-openjdk15-with-mongodb-4.2.0", "ci/openjdk15-mongodb-4.2/") docker.withRegistry('', 'hub.docker.com-springbuildmaster') { image.push() } @@ -139,10 +139,10 @@ pipeline { } } - stage("test: baseline (jdk14)") { + stage("test: baseline (jdk15)") { agent { docker { - image 'springci/spring-data-openjdk14-with-mongodb-4.2.0:latest' + image 'springci/spring-data-openjdk15-with-mongodb-4.2.0:latest' label 'data' args '-v $HOME:/tmp/jenkins-home' } diff --git a/ci/openjdk14-mongodb-4.2/Dockerfile b/ci/openjdk15-mongodb-4.2/Dockerfile similarity index 94% rename from ci/openjdk14-mongodb-4.2/Dockerfile rename to ci/openjdk15-mongodb-4.2/Dockerfile index 5f7d26c929..5f09d5c1d7 100644 --- a/ci/openjdk14-mongodb-4.2/Dockerfile +++ b/ci/openjdk15-mongodb-4.2/Dockerfile @@ -1,4 +1,4 @@ -FROM adoptopenjdk/openjdk14:latest +FROM adoptopenjdk/openjdk15:latest ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive From 1f81806809438ec69a5436c3849421268d785016 Mon Sep 17 00:00:00 2001 From: LiangYong <517219382@qq.com> Date: Sat, 8 Aug 2020 18:19:59 +0800 Subject: [PATCH 0278/1381] DATAMONGO-2638 - Fix aggregation input parameter syntax in reference documentation. Original Pull Request: #881 --- .../asciidoc/reference/mongo-repositories-aggregation.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc b/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc index 8fe1b13dee..6342e9ae48 100644 --- a/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc +++ b/src/main/asciidoc/reference/mongo-repositories-aggregation.adoc @@ -17,10 +17,10 @@ public interface PersonRepository extends CrudReppsitory { @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") List groupByLastnameAndFirstnames(Sort sort); <2> - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $?0 } } }") + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : ?0 } } }") List groupByLastnameAnd(String property); <3> - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $?0 } } }") + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : ?0 } } }") List groupByLastnameAnd(String property, Pageable page); <4> @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") From 76eecc443e7b6f81089a036fbcf6354d3744239c Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Fri, 11 Sep 2020 15:58:09 +0200 Subject: [PATCH 0279/1381] DATAMONGO-2638 - Fix list item rendering in reference documentation. Original Pull Request: #885 --- src/main/asciidoc/reference/mongodb.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 7c6395fc56..7b3cbddadd 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -27,7 +27,7 @@ First, you need to set up a running MongoDB server. Refer to the https://docs.mo To create a Spring project in STS: . Go to File -> New -> Spring Template Project -> Simple Spring Utility Project, and press Yes when prompted. Then enter a project and a package name, such as `org.spring.mongodb.example`. -.Add the following to the pom.xml files `dependencies` element: +. Add the following to the pom.xml files `dependencies` element: + [source,xml,subs="+attributes"] ---- From 56697545a38c094130bcc413c04777d6c4f2b3fa Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 11:02:56 +0100 Subject: [PATCH 0280/1381] DATAMONGO-2641 - Updated changelog. --- src/main/resources/changelog.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index c012660afc..c6b4962e01 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,11 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.1.21.RELEASE (2020-10-28) +---------------------------------------------- +* DATAMONGO-2641 - Release 2.1.21 (Lovelace SR21). + + Changes in version 3.1.0-RC2 (2020-10-14) ----------------------------------------- * DATAMONGO-2633 - @Query annotation does not support $centerSphere. @@ -3185,5 +3190,6 @@ Repository + From 83136b4e60085ea24253d83a9fd4962bf8e359a3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 11:43:53 +0100 Subject: [PATCH 0281/1381] DATAMONGO-2624 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index c6b4962e01..9292889d44 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.11.RELEASE (2020-10-28) +---------------------------------------------- +* DATAMONGO-2638 - Fix documentation issues. +* DATAMONGO-2633 - @Query annotation does not support $centerSphere. +* DATAMONGO-2624 - Release 2.2.11 (Moore SR11). + + Changes in version 2.1.21.RELEASE (2020-10-28) ---------------------------------------------- * DATAMONGO-2641 - Release 2.1.21 (Lovelace SR21). @@ -3191,5 +3198,6 @@ Repository + From 30e63fffe2d063853b849243167c78464cbaef36 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 14:34:04 +0100 Subject: [PATCH 0282/1381] DATAMONGO-2625 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 9292889d44..0455346d51 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.5.RELEASE (2020-10-28) +--------------------------------------------- +* DATAMONGO-2643 - Adopt to AssertJ API changes. +* DATAMONGO-2638 - Fix documentation issues. +* DATAMONGO-2633 - @Query annotation does not support $centerSphere. +* DATAMONGO-2625 - Release 3.0.5 (Neumann SR5). + + Changes in version 2.2.11.RELEASE (2020-10-28) ---------------------------------------------- * DATAMONGO-2638 - Fix documentation issues. @@ -3199,5 +3207,6 @@ Repository + From f5e2bdc7eff9b9e7d1b7b7f43d525144433f6fb0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 15:46:17 +0100 Subject: [PATCH 0283/1381] DATAMONGO-2639 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 0455346d51..6afbc5c333 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.0 (2020-10-28) +------------------------------------- +* DATAMONGO-2642 - Upgrade to MongoDB Driver 4.1.1. +* DATAMONGO-2639 - Release 3.1 GA (2020.0.0). +* DATAMONGO-2638 - Fix documentation issues. + + Changes in version 3.0.5.RELEASE (2020-10-28) --------------------------------------------- * DATAMONGO-2643 - Adopt to AssertJ API changes. @@ -3208,5 +3215,6 @@ Repository + From 373f07e17698d7e6dae3b5c24782655916226694 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 15:46:31 +0100 Subject: [PATCH 0284/1381] DATAMONGO-2639 - Prepare 3.1 GA (2020.0.0). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index b0509f1c29..c18228435f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0-SNAPSHOT + 2.4.0 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0-SNAPSHOT + 2.4.0 4.1.1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-release + https://repo.spring.io/libs-release sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index a806d94ce2..fcb471e1ff 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.1 RC2 (2020.0.0) +Spring Data MongoDB 3.1 GA (2020.0.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -19,3 +19,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From c9251b1b2941af89ff074918df2e85ce345b1e1a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 15:46:54 +0100 Subject: [PATCH 0285/1381] DATAMONGO-2639 - Release version 3.1 GA (2020.0.0). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index c18228435f..fc5acb46c6 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a85b081e26..1900951b15 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 33014c7c4f..7699ab11b9 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ea401d5618..96565e3c33 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0 ../pom.xml From 96f389e580360b0b6a0f1d3382265961c282d55e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 16:10:20 +0100 Subject: [PATCH 0286/1381] DATAMONGO-2639 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index fc5acb46c6..ac41512339 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0 + 3.2.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 1900951b15..f0fbb601c8 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0 + 3.2.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 7699ab11b9..1a17321782 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0 + 3.2.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 96565e3c33..0248517caf 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0 + 3.2.0-SNAPSHOT ../pom.xml From 6ab43c239191b8e48b257671ffbbb91259d5366d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 28 Oct 2020 16:10:23 +0100 Subject: [PATCH 0287/1381] DATAMONGO-2639 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ac41512339..99721676cb 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.4.0 + 2.5.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.4.0 + 2.5.0-SNAPSHOT 4.1.1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-release - https://repo.spring.io/libs-release + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From c7e1ca58630684f220d573f9d2471241b860dea7 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 9 Nov 2020 09:48:26 +0100 Subject: [PATCH 0288/1381] DATAMONGO-2635 - Enforce aggregation pipeline mapping. Avoid using the Aggregation.DEFAULT_CONTEXT which does not map contained values to the according MongoDB representation. We now use a relaxed aggregation context, preserving given field names, where possible. Original pull request: #890. --- .../data/mongodb/core/AggregationUtil.java | 4 +-- .../data/mongodb/core/QueryOperations.java | 5 ++-- .../mongodb/core/ReactiveMongoTemplate.java | 3 ++- .../TypeBasedAggregationOperationContext.java | 12 +++++++-- .../core/aggregation/UnionWithOperation.java | 6 +---- .../core/aggregation/AggregationTests.java | 27 +++++++++++++++++++ 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java index 36fc19a098..2cebf65312 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java @@ -77,7 +77,7 @@ AggregationOperationContext prepareAggregationContext(Aggregation aggregation, } if (!(aggregation instanceof TypedAggregation)) { - return Aggregation.DEFAULT_CONTEXT; + return new RelaxedTypeBasedAggregationOperationContext(Object.class, mappingContext, queryMapper); } Class inputType = ((TypedAggregation) aggregation).getInputType(); @@ -98,7 +98,7 @@ AggregationOperationContext prepareAggregationContext(Aggregation aggregation, */ List createPipeline(Aggregation aggregation, AggregationOperationContext context) { - if (!ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) { + if (ObjectUtils.nullSafeEquals(context, Aggregation.DEFAULT_CONTEXT)) { return aggregation.toPipeline(context); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index 438e53c5dc..659db0811f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -707,10 +707,9 @@ Document getMappedShardKey(MongoPersistentEntity entity) { */ List getUpdatePipeline(@Nullable Class domainType) { - AggregationOperationContext context = domainType != null - ? new RelaxedTypeBasedAggregationOperationContext(domainType, mappingContext, queryMapper) - : Aggregation.DEFAULT_CONTEXT; + Class type = domainType != null ? domainType : Object.class; + AggregationOperationContext context = new RelaxedTypeBasedAggregationOperationContext(type, mappingContext, queryMapper); return aggregationUtil.createPipeline((AggregationUpdate) update, context); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 64fe99f08a..977ceb3944 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,6 +17,7 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -2112,7 +2113,7 @@ List prepareFilter(ChangeStreamOptions options) { AggregationOperationContext context = agg instanceof TypedAggregation ? new TypeBasedAggregationOperationContext(((TypedAggregation) agg).getInputType(), getConverter().getMappingContext(), queryMapper) - : Aggregation.DEFAULT_CONTEXT; + : new RelaxedTypeBasedAggregationOperationContext(Object.class, mappingContext, queryMapper); return agg.toPipeline(new PrefixingDelegatingAggregationOperationContext(context, "fullDocument", Arrays.asList("operationType", "fullDocument", "documentKey", "updateDescription", "ns"))); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java index aab2ffe5f5..a3158e18d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java @@ -21,6 +21,7 @@ import java.util.List; import org.bson.Document; +import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference; @@ -29,6 +30,7 @@ import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.util.Lazy; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -46,6 +48,7 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio private final Class type; private final MappingContext, MongoPersistentProperty> mappingContext; private final QueryMapper mapper; + private final Lazy> entity; /** * Creates a new {@link TypeBasedAggregationOperationContext} for the given type, {@link MappingContext} and @@ -65,6 +68,7 @@ public TypeBasedAggregationOperationContext(Class type, this.type = type; this.mappingContext = mappingContext; this.mapper = mapper; + this.entity = Lazy.of(() -> mappingContext.getPersistentEntity(type)); } /* @@ -151,10 +155,14 @@ public AggregationOperationContext continueOnMissingFieldReference(Class type protected FieldReference getReferenceFor(Field field) { + if(entity.getNullable() == null) { + return new DirectFieldReference(new ExposedField(field, true)); + } + PersistentPropertyPath propertyPath = mappingContext - .getPersistentPropertyPath(field.getTarget(), type); + .getPersistentPropertyPath(field.getTarget(), type); Field mappedField = field(field.getName(), - propertyPath.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE)); + propertyPath.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE)); return new DirectFieldReference(new ExposedField(mappedField, true)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java index 8bbb730b3d..2ebddfd68e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java @@ -142,12 +142,8 @@ public Document toDocument(AggregationOperationContext context) { private AggregationOperationContext computeContext(AggregationOperationContext source) { - if (domainType == null) { - return Aggregation.DEFAULT_CONTEXT; - } - if (source instanceof TypeBasedAggregationOperationContext) { - return ((TypeBasedAggregationOperationContext) source).continueOnMissingFieldReference(domainType); + return ((TypeBasedAggregationOperationContext) source).continueOnMissingFieldReference(domainType != null ? domainType : Object.class); } if (source instanceof ExposedFieldsAggregationOperationContext) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index abc994a050..7eb7f37f33 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -1928,6 +1928,22 @@ void skipOutputDoesNotReadBackAggregationResults() { assertThat(results.getRawResults()).isEmpty(); } + @Test // DATAMONGO-2635 + void mapsEnumsInMatchClauseUsingInCriteriaCorrectly() { + + WithEnum source = new WithEnum(); + source.enumValue = MyEnum.TWO; + source.id = "id-1"; + + mongoTemplate.save(source); + + Aggregation agg = newAggregation(match(where("enumValue").in(Collections.singletonList(MyEnum.TWO)))); + + AggregationResults results = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(WithEnum.class), + Document.class); + assertThat(results.getMappedResults()).hasSize(1); + } + private void createUsersWithReferencedPersons() { mongoTemplate.dropCollection(User.class); @@ -2240,4 +2256,15 @@ static class ComplexId { String p1; String p2; } + + static enum MyEnum { + ONE, TWO + } + + @lombok.Data + static class WithEnum { + + @Id String id; + MyEnum enumValue; + } } From 07c728bb32ce81a7e40552d691b952c08d84b343 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 9 Nov 2020 11:15:54 +0100 Subject: [PATCH 0289/1381] DATAMONGO-2644 - ProjectOperation no longer errors on inclusion of default _id field. Original pull request: #890. --- .../core/aggregation/ProjectionOperation.java | 10 +++++++++- .../core/aggregation/AggregationUnitTests.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index 21278041ae..82a1de69d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -264,7 +264,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), fieldObject); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ @@ -1450,6 +1450,14 @@ private Object renderFieldValue(AggregationOperationContext context) { return field.getTarget(); } + if (field.getTarget().equals(Fields.UNDERSCORE_ID)) { + try { + return context.getReference(field).getReferenceValue(); + } catch (java.lang.IllegalArgumentException e) { + return Fields.UNDERSCORE_ID_REF; + } + } + // check whether referenced field exists in the context return context.getReference(field).getReferenceValue(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java index e51932abe7..37dc8727f7 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUnitTests.java @@ -29,6 +29,11 @@ import org.junit.jupiter.api.Test; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond; +import org.springframework.data.mongodb.core.aggregation.ProjectionOperationUnitTests.BookWithFieldAnnotation; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.Criteria; /** @@ -582,6 +587,17 @@ void shouldAllowInternalThisAndValueReferences() { "{\"attributeRecordArrays\": {\"$reduce\": {\"input\": \"$attributeRecordArrays\", \"initialValue\": [], \"in\": {\"$concatArrays\": [\"$$value\", \"$$this\"]}}}}")); } + @Test // DATAMONGO-2644 + void projectOnIdIsAlwaysValid() { + + MongoMappingContext mappingContext = new MongoMappingContext(); + Document target = new Aggregation(bucket("start"), project("_id")).toDocument("collection-1", + new RelaxedTypeBasedAggregationOperationContext(BookWithFieldAnnotation.class, mappingContext, + new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)))); + + assertThat(extractPipelineElement(target, 1, "$project")).isEqualTo(Document.parse(" { \"_id\" : \"$_id\" }")); + } + private Document extractPipelineElement(Document agg, int index, String operation) { List pipeline = (List) agg.get("pipeline"); From 5c3bb00b24257571ddb5df6f36e475522c30b557 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 11 Nov 2020 11:58:18 +0100 Subject: [PATCH 0290/1381] DATAMONGO-2648 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 6afbc5c333..e78eff57bd 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.1 (2020-11-11) +------------------------------------- +* DATAMONGO-2648 - Release 3.1.1 (2020.0.1). +* DATAMONGO-2644 - Invalid reference '_id'! Error In spring data mongodb. +* DATAMONGO-2635 - Enums Don't Properly Serialize In Aggregation Pipeline Facet. + + Changes in version 3.1.0 (2020-10-28) ------------------------------------- * DATAMONGO-2642 - Upgrade to MongoDB Driver 4.1.1. @@ -3216,5 +3223,6 @@ Repository + From c1a8ffec96ff23adb7e1bb6d655cd89e2eef2537 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 10 Nov 2020 16:48:36 +0100 Subject: [PATCH 0291/1381] DATAMONGO-2652 - Implements CrudRepository and ReactiveCrudRepository.delete(Iterable ids). See also: DATACMNS-800. Original pull request: #892. --- .../support/SimpleMongoRepository.java | 11 +++++- .../SimpleReactiveMongoRepository.java | 31 +++++++++++++--- .../ReactiveMongoRepositoryTests.java | 36 +++++++++++++------ .../support/SimpleMongoRepositoryTests.java | 20 ++++++++--- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index b00ca61a34..e934e741ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -51,6 +51,7 @@ * @author Thomas Darimont * @author Mark Paluch * @author Mehran Behnam + * @author Jens Schauder */ public class SimpleMongoRepository implements MongoRepository { @@ -182,11 +183,19 @@ public void delete(T entity) { @Override public void deleteAll(Iterable entities) { - Assert.notNull(entities, "The given Iterable of entities not be null!"); + Assert.notNull(entities, "The given Iterable of entities must not be null!"); entities.forEach(this::delete); } + @Override + public void deleteAllById(Iterable ids) { + + Assert.notNull(ids, "The given Iterable of ids must not be null!"); + + ids.forEach(this::deleteById); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.CrudRepository#deleteAll() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 0a1b05db3d..30deb56c56 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -17,10 +17,8 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import java.io.Serializable; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @@ -40,6 +38,9 @@ import com.mongodb.client.result.DeleteResult; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + /** * Reactive repository base implementation for Mongo. * @@ -47,6 +48,7 @@ * @author Oliver Gierke * @author Christoph Strobl * @author Ruben J Garcia + * @author Jens Schauder * @since 2.0 */ public class SimpleReactiveMongoRepository implements ReactiveMongoRepository { @@ -401,7 +403,28 @@ public Mono deleteAll(Iterable entities) { Assert.notNull(entities, "The given Iterable of entities must not be null!"); - return Flux.fromIterable(entities).flatMap(this::delete).then(); + Collection idCollection = StreamUtils.createStreamFromIterator(entities.iterator()) + .map(entityInformation::getId) + .collect(Collectors.toList()); + + Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + + return mongoOperations + .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) + .then(); + } + + @Override + public Mono deleteAllById(Iterable ids) { + + Assert.notNull(ids, "The given Iterable of ids must not be null!"); + + Collection idCollection = StreamUtils.createStreamFromIterator(ids.iterator()).collect(Collectors.toList()); + Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + + return mongoOperations + .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) + .then(); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index 09700dcfc1..43c0fb9962 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.repository; +import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.domain.Sort.Direction.*; import static org.springframework.data.mongodb.core.query.Criteria.*; @@ -66,7 +67,6 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor; import org.springframework.data.repository.Repository; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -77,10 +77,12 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Jens Schauder */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class ReactiveMongoRepositoryTests { + public static final int PERSON_COUNT = 7; static @Client MongoClient mongoClient; @Autowired ReactiveMongoTemplate template; @@ -154,17 +156,17 @@ public void setUp() throws Exception { dave = new Person("Dave", "Matthews", 42); oliver = new Person("Oliver August", "Matthews", 4); carter = new Person("Carter", "Beauford", 49); - carter.setSkills(Arrays.asList("Drums", "percussion", "vocals")); + carter.setSkills(asList("Drums", "percussion", "vocals")); Thread.sleep(10); boyd = new Person("Boyd", "Tinsley", 45); - boyd.setSkills(Arrays.asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); + boyd.setSkills(asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); stefan = new Person("Stefan", "Lessard", 34); leroi = new Person("Leroi", "Moore", 41); alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); - repository.saveAll(Arrays.asList(oliver, carter, boyd, stefan, leroi, alicia, dave)).as(StepVerifier::create) // - .expectNextCount(7) // + repository.saveAll(asList(oliver, carter, boyd, stefan, leroi, alicia, dave)).as(StepVerifier::create) // + .expectNextCount(PERSON_COUNT) // .verifyComplete(); } @@ -411,7 +413,7 @@ public void considersRepositoryCollectionName() { leroi.id = null; boyd.id = null; - contactRepository.saveAll(Arrays.asList(leroi, boyd)) // + contactRepository.saveAll(asList(leroi, boyd)) // .as(StepVerifier::create) // .expectNextCount(2) // .verifyComplete(); @@ -430,7 +432,7 @@ public void considersRepositoryCollectionName() { @Test // DATAMONGO-2182 public void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { - repository.findAll(person.id.in(Arrays.asList(dave.id, carter.id))) // + repository.findAll(person.id.in(asList(dave.id, carter.id))) // .collectList() // .as(StepVerifier::create) // .assertNext(actual -> { @@ -468,7 +470,7 @@ public void annotatedAggregationWithPlaceholderValue() { .contains(new PersonAggregate("Tinsley", "Boyd")) // .contains(new PersonAggregate("Beauford", "Carter")) // .contains(new PersonAggregate("Moore", "Leroi")) // - .contains(new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August"))); + .contains(new PersonAggregate("Matthews", asList("Dave", "Oliver August"))); }).verifyComplete(); } @@ -484,7 +486,7 @@ public void annotatedAggregationWithSort() { new PersonAggregate("Beauford", "Carter"), // new PersonAggregate("Keys", "Alicia"), // new PersonAggregate("Lessard", "Stefan"), // - new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August")), // + new PersonAggregate("Matthews", asList("Dave", "Oliver August")), // new PersonAggregate("Moore", "Leroi"), // new PersonAggregate("Tinsley", "Boyd")); }) // @@ -501,7 +503,7 @@ public void annotatedAggregationWithPageable() { assertThat(actual) // .containsExactly( // new PersonAggregate("Lessard", "Stefan"), // - new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August"))); + new PersonAggregate("Matthews", asList("Dave", "Oliver August"))); }) // .verifyComplete(); } @@ -576,7 +578,7 @@ public void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { Person p3 = new Person(firstname, null); p3.setEmail("p3@example.com"); - repository.saveAll(Arrays.asList(p1, p2, p3)).then().as(StepVerifier::create).verifyComplete(); + repository.saveAll(asList(p1, p2, p3)).then().as(StepVerifier::create).verifyComplete(); repository.projectToLastnameAndRemoveId(firstname) // .as(StepVerifier::create) // @@ -617,6 +619,18 @@ public void deleteByShouldAllowSingleDocumentRemovalCorrectly() { .verifyComplete(); } + @Test // DATAMONGO-2652 + public void deleteAllById() { + + repository.deleteAllById(asList(carter.id, dave.id)) // + .as(StepVerifier::create) // + .verifyComplete(); + + repository.count().as(StepVerifier::create) // + .expectNext(PERSON_COUNT - 2L) // + .verifyComplete(); + } + interface ReactivePersonRepository extends ReactiveMongoRepository, ReactiveQuerydslPredicateExecutor { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 9cf066acea..1455547a48 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -15,11 +15,11 @@ */ package org.springframework.data.mongodb.repository.support; +import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.domain.ExampleMatcher.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -58,6 +58,7 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author Jens Schauder */ @ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) public class SimpleMongoRepositoryTests { @@ -85,11 +86,11 @@ public void setUp() { leroi = new Person("Leroi", "Moore", 41); alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); - all = repository.saveAll(Arrays.asList(oliver, dave, carter, boyd, stefan, leroi, alicia)); + all = repository.saveAll(asList(oliver, dave, carter, boyd, stefan, leroi, alicia)); } @Test - public void findALlFromCustomCollectionName() { + public void findAllFromCustomCollectionName() { assertThat(repository.findAll()).hasSize(all.size()); } @@ -384,7 +385,7 @@ public void saveAllUsesEntityCollection() { repository.deleteAll(); - repository.saveAll(Arrays.asList(first, second)); + repository.saveAll(asList(first, second)); assertThat(repository.findAll()).containsExactlyInAnyOrder(first, second); } @@ -435,6 +436,17 @@ public void existsShouldBePossibleInTransaction() { assertThat(exists).isTrue(); } + @Test // DATAMONGO-2652 + public void deleteAllByIds() { + + repository.deleteAllById(asList(dave.getId(), carter.getId())); + + assertThat(repository.findAll()) // + .hasSize(all.size() - 2) // + .doesNotContain(dave) // + .doesNotContain(carter); + } + private void assertThatAllReferencePersonsWereStoredCorrectly(Map references, List saved) { for (Person person : saved) { From ab4fe5cb0b54796659fe3c9d9fac0857a2183bad Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 25 Nov 2020 11:33:54 +0100 Subject: [PATCH 0292/1381] DATAMONGO-2652 - Polishing. Reorder implementation methods. Reduce visibility of test methods according to JUnit 5 requirements. Original pull request: #892. --- .../repository/ReactiveMongoRepository.java | 12 - .../support/SimpleMongoRepository.java | 128 +++--- .../SimpleReactiveMongoRepository.java | 363 ++++++++++-------- .../ReactiveMongoRepositoryTests.java | 120 +++--- .../support/SimpleMongoRepositoryTests.java | 70 ++-- 5 files changed, 363 insertions(+), 330 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java index ff78e7282c..1a45a11bdb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java @@ -64,16 +64,4 @@ public interface ReactiveMongoRepository extends ReactiveSortingRepositor */ Flux insert(Publisher entities); - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example) - */ - Flux findAll(Example example); - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort) - */ - Flux findAll(Example example, Sort sort); - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index e934e741ec..3c26dbc8d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -73,6 +73,10 @@ public SimpleMongoRepository(MongoEntityInformation metadata, MongoOperat this.mongoOperations = mongoOperations; } + // ------------------------------------------------------------------------- + // Methods from CrudRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object) @@ -136,6 +140,27 @@ public boolean existsById(ID id) { entityInformation.getCollectionName()); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#findAll() + */ + @Override + public List findAll() { + return findAll(new Query()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#findAllById(java.lang.Iterable) + */ + @Override + public Iterable findAllById(Iterable ids) { + + Assert.notNull(ids, "The given Ids of entities not be null!"); + + return findAll(getIdQuery(ids)); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.CrudRepository#count() @@ -178,55 +203,42 @@ public void delete(T entity) { /* * (non-Javadoc) - * @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable) + * @see org.springframework.data.repository.CrudRepository#deleteAllById(java.lang.Iterable) */ - @Override - public void deleteAll(Iterable entities) { - - Assert.notNull(entities, "The given Iterable of entities must not be null!"); - - entities.forEach(this::delete); - } - @Override public void deleteAllById(Iterable ids) { Assert.notNull(ids, "The given Iterable of ids must not be null!"); - ids.forEach(this::deleteById); + mongoOperations.remove(getIdQuery(ids), entityInformation.getJavaType(), + entityInformation.getCollectionName()); } /* * (non-Javadoc) - * @see org.springframework.data.repository.CrudRepository#deleteAll() + * @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable) */ @Override - public void deleteAll() { - mongoOperations.remove(new Query(), entityInformation.getCollectionName()); - } + public void deleteAll(Iterable entities) { - /* - * (non-Javadoc) - * @see org.springframework.data.repository.CrudRepository#findAll() - */ - @Override - public List findAll() { - return findAll(new Query()); + Assert.notNull(entities, "The given Iterable of entities must not be null!"); + + entities.forEach(this::delete); } /* * (non-Javadoc) - * @see org.springframework.data.repository.CrudRepository#findAllById(java.lang.Iterable) + * @see org.springframework.data.repository.CrudRepository#deleteAll() */ @Override - public Iterable findAllById(Iterable ids) { - - Assert.notNull(ids, "The given Ids of entities not be null!"); - - return findAll(new Query(new Criteria(entityInformation.getIdAttribute()) - .in(Streamable.of(ids).stream().collect(StreamUtils.toUnmodifiableList())))); + public void deleteAll() { + mongoOperations.remove(new Query(), entityInformation.getCollectionName()); } + // ------------------------------------------------------------------------- + // Methods from PagingAndSortingRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Pageable) @@ -254,6 +266,10 @@ public List findAll(Sort sort) { return findAll(new Query().with(sort)); } + // ------------------------------------------------------------------------- + // Methods from MongoRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) * @see org.springframework.data.mongodb.repository.MongoRepository#insert(java.lang.Object) @@ -284,23 +300,33 @@ public List insert(Iterable entities) { return new ArrayList<>(mongoOperations.insertAll(list)); } + // ------------------------------------------------------------------------- + // Methods from QueryByExampleExecutor + // ------------------------------------------------------------------------- + /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example, org.springframework.data.domain.Pageable) + * @see org.springframework.data.repository.query.QueryByExampleExecutor#findOne(org.springframework.data.domain.Example) */ @Override - public Page findAll(final Example example, Pageable pageable) { + public Optional findOne(Example example) { Assert.notNull(example, "Sample must not be null!"); - Assert.notNull(pageable, "Pageable must not be null!"); Query query = new Query(new Criteria().alike(example)) // - .collation(entityInformation.getCollation()).with(pageable); // + .collation(entityInformation.getCollation()); - List list = mongoOperations.find(query, example.getProbeType(), entityInformation.getCollectionName()); + return Optional + .ofNullable(mongoOperations.findOne(query, example.getProbeType(), entityInformation.getCollectionName())); + } - return PageableExecutionUtils.getPage(list, pageable, - () -> mongoOperations.count(Query.of(query).limit(-1).skip(-1), example.getProbeType(), entityInformation.getCollectionName())); + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example) + */ + @Override + public List findAll(Example example) { + return findAll(example, Sort.unsorted()); } /* @@ -322,27 +348,21 @@ public List findAll(Example example, Sort sort) { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example) - */ - @Override - public List findAll(Example example) { - return findAll(example, Sort.unsorted()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryByExampleExecutor#findOne(org.springframework.data.domain.Example) + * @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example, org.springframework.data.domain.Pageable) */ @Override - public Optional findOne(Example example) { + public Page findAll(Example example, Pageable pageable) { Assert.notNull(example, "Sample must not be null!"); + Assert.notNull(pageable, "Pageable must not be null!"); Query query = new Query(new Criteria().alike(example)) // - .collation(entityInformation.getCollation()); + .collation(entityInformation.getCollation()).with(pageable); // - return Optional - .ofNullable(mongoOperations.findOne(query, example.getProbeType(), entityInformation.getCollectionName())); + List list = mongoOperations.find(query, example.getProbeType(), entityInformation.getCollectionName()); + + return PageableExecutionUtils.getPage(list, pageable, + () -> mongoOperations.count(Query.of(query).limit(-1).skip(-1), example.getProbeType(), entityInformation.getCollectionName())); } /* @@ -375,6 +395,10 @@ public boolean exists(Example example) { return mongoOperations.exists(query, example.getProbeType(), entityInformation.getCollectionName()); } + // ------------------------------------------------------------------------- + // Utility methods + // ------------------------------------------------------------------------- + private Query getIdQuery(Object id) { return new Query(getIdCriteria(id)); } @@ -383,6 +407,11 @@ private Criteria getIdCriteria(Object id) { return where(entityInformation.getIdAttribute()).is(id); } + private Query getIdQuery(Iterable ids) { + return new Query(new Criteria(entityInformation.getIdAttribute()) + .in(Streamable.of(ids).stream().collect(StreamUtils.toUnmodifiableList()))); + } + private List findAll(@Nullable Query query) { if (query == null) { @@ -391,4 +420,5 @@ private List findAll(@Nullable Query query) { return mongoOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName()); } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 30deb56c56..2390b5959d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -17,12 +17,16 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import org.reactivestreams.Publisher; + import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.domain.Example; @@ -38,9 +42,6 @@ import com.mongodb.client.result.DeleteResult; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * Reactive repository base implementation for Mongo. * @@ -66,52 +67,79 @@ public SimpleReactiveMongoRepository(MongoEntityInformation entityInforma this.mongoOperations = mongoOperations; } + // ------------------------------------------------------------------------- + // Methods from ReactiveCrudRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(java.lang.Object) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#save(java.lang.Object) */ @Override - public Mono findById(ID id) { + public Mono save(S entity) { - Assert.notNull(id, "The given id must not be null!"); + Assert.notNull(entity, "Entity must not be null!"); - return mongoOperations.findById(id, entityInformation.getJavaType(), entityInformation.getCollectionName()); + if (entityInformation.isNew(entity)) { + return mongoOperations.insert(entity, entityInformation.getCollectionName()); + } + + return mongoOperations.save(entity, entityInformation.getCollectionName()); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(org.reactivestreams.Publisher) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#saveAll(java.lang.Iterable) */ @Override - public Mono findById(Publisher publisher) { + public Flux saveAll(Iterable entities) { - Assert.notNull(publisher, "The given id must not be null!"); + Assert.notNull(entities, "The given Iterable of entities must not be null!"); - return Mono.from(publisher).flatMap( - id -> mongoOperations.findById(id, entityInformation.getJavaType(), entityInformation.getCollectionName())); + Streamable source = Streamable.of(entities); + + return source.stream().allMatch(entityInformation::isNew) ? // + mongoOperations.insert(source.stream().collect(Collectors.toList()), entityInformation.getCollectionName()) : // + Flux.fromIterable(entities).flatMap(this::save); } /* * (non-Javadoc) - * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#findOne(org.springframework.data.domain.Example) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#saveAll(org.reactivestreams.Publisher) */ @Override - public Mono findOne(Example example) { + public Flux saveAll(Publisher entityStream) { - Assert.notNull(example, "Sample must not be null!"); + Assert.notNull(entityStream, "The given Publisher of entities must not be null!"); - Query query = new Query(new Criteria().alike(example)) // - .collation(entityInformation.getCollation()) // - .limit(2); + return Flux.from(entityStream).flatMap(entity -> entityInformation.isNew(entity) ? // + mongoOperations.insert(entity, entityInformation.getCollectionName()).then(Mono.just(entity)) : // + mongoOperations.save(entity, entityInformation.getCollectionName()).then(Mono.just(entity))); + } - return mongoOperations.find(query, example.getProbeType(), entityInformation.getCollectionName()).buffer(2) - .map(vals -> { + /* + * (non-Javadoc) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(java.lang.Object) + */ + @Override + public Mono findById(ID id) { - if (vals.size() > 1) { - throw new IncorrectResultSizeDataAccessException(1); - } - return vals.iterator().next(); - }).next(); + Assert.notNull(id, "The given id must not be null!"); + + return mongoOperations.findById(id, entityInformation.getJavaType(), entityInformation.getCollectionName()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(org.reactivestreams.Publisher) + */ + @Override + public Mono findById(Publisher publisher) { + + Assert.notNull(publisher, "The given id must not be null!"); + + return Mono.from(publisher).flatMap( + id -> mongoOperations.findById(id, entityInformation.getJavaType(), entityInformation.getCollectionName())); } /* @@ -138,22 +166,6 @@ public Mono existsById(Publisher publisher) { return Mono.from(publisher).flatMap(id -> mongoOperations.exists(getIdQuery(id), entityInformation.getJavaType(), entityInformation.getCollectionName())); - - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#exists(org.springframework.data.domain.Example) - */ - @Override - public Mono exists(Example example) { - - Assert.notNull(example, "Sample must not be null!"); - - Query query = new Query(new Criteria().alike(example)) // - .collation(entityInformation.getCollation()); - - return mongoOperations.exists(query, example.getProbeType(), entityInformation.getCollectionName()); } /* @@ -174,8 +186,7 @@ public Flux findAllById(Iterable ids) { Assert.notNull(ids, "The given Iterable of Id's must not be null!"); - return findAll(new Query(new Criteria(entityInformation.getIdAttribute()) - .in(Streamable.of(ids).stream().collect(StreamUtils.toUnmodifiableList())))); + return findAll(getIdQuery(ids)); } /* @@ -192,265 +203,270 @@ public Flux findAllById(Publisher ids) { /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveSortingRepository#findAll(org.springframework.data.domain.Sort) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#count() */ @Override - public Flux findAll(Sort sort) { - - Assert.notNull(sort, "Sort must not be null!"); - - return findAll(new Query().with(sort)); + public Mono count() { + return mongoOperations.count(new Query(), entityInformation.getCollectionName()); } + /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteById(java.lang.Object) */ @Override - public Flux findAll(Example example, Sort sort) { - - Assert.notNull(example, "Sample must not be null!"); - Assert.notNull(sort, "Sort must not be null!"); + public Mono deleteById(ID id) { - Query query = new Query(new Criteria().alike(example)) // - .collation(entityInformation.getCollation()) // - .with(sort); + Assert.notNull(id, "The given id must not be null!"); - return mongoOperations.find(query, example.getProbeType(), entityInformation.getCollectionName()); + return mongoOperations + .remove(getIdQuery(id), entityInformation.getJavaType(), entityInformation.getCollectionName()).then(); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#findAll(org.springframework.data.domain.Example) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteById(org.reactivestreams.Publisher) */ @Override - public Flux findAll(Example example) { + public Mono deleteById(Publisher publisher) { - Assert.notNull(example, "Example must not be null!"); + Assert.notNull(publisher, "Id must not be null!"); - return findAll(example, Sort.unsorted()); + return Mono.from(publisher).flatMap(id -> mongoOperations.remove(getIdQuery(id), entityInformation.getJavaType(), + entityInformation.getCollectionName())).then(); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#count() + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#delete(java.lang.Object) */ @Override - public Mono count() { - return mongoOperations.count(new Query(), entityInformation.getCollectionName()); - } + public Mono delete(T entity) { - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#count(org.springframework.data.domain.Example) - */ - @Override - public Mono count(Example example) { + Assert.notNull(entity, "The given entity must not be null!"); - Assert.notNull(example, "Sample must not be null!"); + Mono remove = mongoOperations.remove(entity, entityInformation.getCollectionName()); - Query query = new Query(new Criteria().alike(example)) // - .collation(entityInformation.getCollation()); + if (entityInformation.isVersioned()) { - return mongoOperations.count(query, example.getProbeType(), entityInformation.getCollectionName()); + remove = remove.handle((deleteResult, sink) -> { + + if (deleteResult.wasAcknowledged() && deleteResult.getDeletedCount() == 0) { + sink.error(new OptimisticLockingFailureException(String.format( + "The entity with id %s with version %s in %s cannot be deleted! Was it modified or deleted in the meantime?", + entityInformation.getId(entity), entityInformation.getVersion(entity), + entityInformation.getCollectionName()))); + } else { + sink.next(deleteResult); + } + }); + } + + return remove.then(); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(java.lang.Object) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAllById(java.lang.Iterable) */ @Override - public Mono insert(S entity) { + public Mono deleteAllById(Iterable ids) { - Assert.notNull(entity, "Entity must not be null!"); + Assert.notNull(ids, "The given Iterable of Id's must not be null!"); - return mongoOperations.insert(entity, entityInformation.getCollectionName()); + return mongoOperations + .remove(getIdQuery(ids), entityInformation.getJavaType(), entityInformation.getCollectionName()).then(); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(java.lang.Iterable) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll(java.lang.Iterable) */ @Override - public Flux insert(Iterable entities) { + public Mono deleteAll(Iterable entities) { Assert.notNull(entities, "The given Iterable of entities must not be null!"); - List source = Streamable.of(entities).stream().collect(StreamUtils.toUnmodifiableList()); + Collection idCollection = StreamUtils.createStreamFromIterator(entities.iterator()).map(entityInformation::getId) + .collect(Collectors.toList()); - return source.isEmpty() ? Flux.empty() : Flux.from(mongoOperations.insertAll(source)); + Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + + return mongoOperations + .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) + .then(); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(org.reactivestreams.Publisher) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll(org.reactivestreams.Publisher) */ @Override - public Flux insert(Publisher entities) { + public Mono deleteAll(Publisher entityStream) { - Assert.notNull(entities, "The given Publisher of entities must not be null!"); + Assert.notNull(entityStream, "The given Publisher of entities must not be null!"); - return Flux.from(entities).flatMap(entity -> mongoOperations.insert(entity, entityInformation.getCollectionName())); + return Flux.from(entityStream)// + .map(entityInformation::getRequiredId)// + .flatMap(this::deleteById)// + .then(); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#save(java.lang.Object) + * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll() */ @Override - public Mono save(S entity) { - - Assert.notNull(entity, "Entity must not be null!"); - - if (entityInformation.isNew(entity)) { - return mongoOperations.insert(entity, entityInformation.getCollectionName()); - } - - return mongoOperations.save(entity, entityInformation.getCollectionName()); + public Mono deleteAll() { + return mongoOperations.remove(new Query(), entityInformation.getCollectionName()).then(Mono.empty()); } + // ------------------------------------------------------------------------- + // Methods from ReactiveSortingRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#saveAll(java.lang.Iterable) + * @see org.springframework.data.repository.reactive.ReactiveSortingRepository#findAll(org.springframework.data.domain.Sort) */ @Override - public Flux saveAll(Iterable entities) { - - Assert.notNull(entities, "The given Iterable of entities must not be null!"); + public Flux findAll(Sort sort) { - Streamable source = Streamable.of(entities); + Assert.notNull(sort, "Sort must not be null!"); - return source.stream().allMatch(entityInformation::isNew) ? // - mongoOperations.insert(source.stream().collect(Collectors.toList()), entityInformation.getCollectionName()) : // - Flux.fromIterable(entities).flatMap(this::save); + return findAll(new Query().with(sort)); } + // ------------------------------------------------------------------------- + // Methods from ReactiveMongoRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#saveAll(org.reactivestreams.Publisher) + * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(java.lang.Object) */ @Override - public Flux saveAll(Publisher entityStream) { + public Mono insert(S entity) { - Assert.notNull(entityStream, "The given Publisher of entities must not be null!"); + Assert.notNull(entity, "Entity must not be null!"); - return Flux.from(entityStream).flatMap(entity -> entityInformation.isNew(entity) ? // - mongoOperations.insert(entity, entityInformation.getCollectionName()).then(Mono.just(entity)) : // - mongoOperations.save(entity, entityInformation.getCollectionName()).then(Mono.just(entity))); + return mongoOperations.insert(entity, entityInformation.getCollectionName()); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteById(java.lang.Object) + * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(java.lang.Iterable) */ @Override - public Mono deleteById(ID id) { + public Flux insert(Iterable entities) { - Assert.notNull(id, "The given id must not be null!"); + Assert.notNull(entities, "The given Iterable of entities must not be null!"); - return mongoOperations - .remove(getIdQuery(id), entityInformation.getJavaType(), entityInformation.getCollectionName()).then(); + List source = Streamable.of(entities).stream().collect(StreamUtils.toUnmodifiableList()); + + return source.isEmpty() ? Flux.empty() : Flux.from(mongoOperations.insertAll(source)); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteById(org.reactivestreams.Publisher) + * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(org.reactivestreams.Publisher) */ @Override - public Mono deleteById(Publisher publisher) { + public Flux insert(Publisher entities) { - Assert.notNull(publisher, "Id must not be null!"); + Assert.notNull(entities, "The given Publisher of entities must not be null!"); - return Mono.from(publisher).flatMap(id -> mongoOperations.remove(getIdQuery(id), entityInformation.getJavaType(), - entityInformation.getCollectionName())).then(); + return Flux.from(entities).flatMap(entity -> mongoOperations.insert(entity, entityInformation.getCollectionName())); } + // ------------------------------------------------------------------------- + // Methods from ReactiveMongoRepository + // ------------------------------------------------------------------------- + /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#delete(java.lang.Object) + * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#findOne(org.springframework.data.domain.Example) */ @Override - public Mono delete(T entity) { - - Assert.notNull(entity, "The given entity must not be null!"); - - Mono remove = mongoOperations.remove(entity, entityInformation.getCollectionName()); + public Mono findOne(Example example) { - if (entityInformation.isVersioned()) { + Assert.notNull(example, "Sample must not be null!"); - remove = remove.handle((deleteResult, sink) -> { + Query query = new Query(new Criteria().alike(example)) // + .collation(entityInformation.getCollation()) // + .limit(2); - if (deleteResult.wasAcknowledged() && deleteResult.getDeletedCount() == 0) { - sink.error(new OptimisticLockingFailureException(String.format( - "The entity with id %s with version %s in %s cannot be deleted! Was it modified or deleted in the meantime?", - entityInformation.getId(entity), entityInformation.getVersion(entity), - entityInformation.getCollectionName()))); - } else { - sink.next(deleteResult); - } - }); - } + return mongoOperations.find(query, example.getProbeType(), entityInformation.getCollectionName()).buffer(2) + .map(vals -> { - return remove.then(); + if (vals.size() > 1) { + throw new IncorrectResultSizeDataAccessException(1); + } + return vals.iterator().next(); + }).next(); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll(java.lang.Iterable) + * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#findAll(org.springframework.data.domain.Example) */ @Override - public Mono deleteAll(Iterable entities) { - - Assert.notNull(entities, "The given Iterable of entities must not be null!"); - - Collection idCollection = StreamUtils.createStreamFromIterator(entities.iterator()) - .map(entityInformation::getId) - .collect(Collectors.toList()); + public Flux findAll(Example example) { - Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + Assert.notNull(example, "Example must not be null!"); - return mongoOperations - .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) - .then(); + return findAll(example, Sort.unsorted()); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort) + */ @Override - public Mono deleteAllById(Iterable ids) { + public Flux findAll(Example example, Sort sort) { - Assert.notNull(ids, "The given Iterable of ids must not be null!"); + Assert.notNull(example, "Sample must not be null!"); + Assert.notNull(sort, "Sort must not be null!"); - Collection idCollection = StreamUtils.createStreamFromIterator(ids.iterator()).collect(Collectors.toList()); - Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + Query query = new Query(new Criteria().alike(example)) // + .collation(entityInformation.getCollation()) // + .with(sort); - return mongoOperations - .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) - .then(); + return mongoOperations.find(query, example.getProbeType(), entityInformation.getCollectionName()); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll(org.reactivestreams.Publisher) + * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#count(org.springframework.data.domain.Example) */ @Override - public Mono deleteAll(Publisher entityStream) { + public Mono count(Example example) { - Assert.notNull(entityStream, "The given Publisher of entities must not be null!"); + Assert.notNull(example, "Sample must not be null!"); - return Flux.from(entityStream)// - .map(entityInformation::getRequiredId)// - .flatMap(this::deleteById)// - .then(); + Query query = new Query(new Criteria().alike(example)) // + .collation(entityInformation.getCollation()); + + return mongoOperations.count(query, example.getProbeType(), entityInformation.getCollectionName()); } /* * (non-Javadoc) - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll() + * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#exists(org.springframework.data.domain.Example) */ @Override - public Mono deleteAll() { - return mongoOperations.remove(new Query(), entityInformation.getCollectionName()).then(Mono.empty()); + public Mono exists(Example example) { + + Assert.notNull(example, "Sample must not be null!"); + + Query query = new Query(new Criteria().alike(example)) // + .collation(entityInformation.getCollation()); + + return mongoOperations.exists(query, example.getProbeType(), entityInformation.getCollectionName()); } + private Query getIdQuery(Object id) { return new Query(getIdCriteria(id)); } @@ -459,6 +475,13 @@ private Criteria getIdCriteria(Object id) { return where(entityInformation.getIdAttribute()).is(id); } + private Query getIdQuery(Iterable ids) { + Collection idCollection = StreamUtils.createStreamFromIterator(ids.iterator()).collect(Collectors.toList()); + Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + + return new Query(idsInCriteria); + } + private Flux findAll(Query query) { return mongoOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index 43c0fb9962..9a35162009 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.repository; -import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.domain.Sort.Direction.*; import static org.springframework.data.mongodb.core.query.Criteria.*; @@ -80,10 +79,10 @@ * @author Jens Schauder */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) -public class ReactiveMongoRepositoryTests { +class ReactiveMongoRepositoryTests { - public static final int PERSON_COUNT = 7; - static @Client MongoClient mongoClient; + private static final int PERSON_COUNT = 7; + private static @Client MongoClient mongoClient; @Autowired ReactiveMongoTemplate template; @@ -91,8 +90,8 @@ public class ReactiveMongoRepositoryTests { @Autowired ReactiveContactRepository contactRepository; @Autowired ReactiveCappedCollectionRepository cappedRepository; - Person dave, oliver, carter, boyd, stefan, leroi, alicia; - QPerson person = QPerson.person; + private Person dave, oliver, carter, boyd, stefan, leroi, alicia; + private QPerson person = QPerson.person; @Configuration static class Config extends AbstractReactiveMongoConfiguration { @@ -142,59 +141,59 @@ protected boolean autoIndexCreation() { } @BeforeAll - public static void cleanDb() { + static void cleanDb() { MongoTestUtils.createOrReplaceCollectionNow("reactive", "person", mongoClient); MongoTestUtils.createOrReplaceCollectionNow("reactive", "capped", mongoClient); } @BeforeEach - public void setUp() throws Exception { + void setUp() throws Exception { repository.deleteAll().as(StepVerifier::create).verifyComplete(); dave = new Person("Dave", "Matthews", 42); oliver = new Person("Oliver August", "Matthews", 4); carter = new Person("Carter", "Beauford", 49); - carter.setSkills(asList("Drums", "percussion", "vocals")); + carter.setSkills(Arrays.asList("Drums", "percussion", "vocals")); Thread.sleep(10); boyd = new Person("Boyd", "Tinsley", 45); - boyd.setSkills(asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); + boyd.setSkills(Arrays.asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); stefan = new Person("Stefan", "Lessard", 34); leroi = new Person("Leroi", "Moore", 41); alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); - repository.saveAll(asList(oliver, carter, boyd, stefan, leroi, alicia, dave)).as(StepVerifier::create) // + repository.saveAll(Arrays.asList(oliver, carter, boyd, stefan, leroi, alicia, dave)).as(StepVerifier::create) // .expectNextCount(PERSON_COUNT) // .verifyComplete(); } @Test // DATAMONGO-1444 - public void shouldFindByLastName() { + void shouldFindByLastName() { repository.findByLastname(dave.getLastname()).as(StepVerifier::create).expectNextCount(2).verifyComplete(); } @Test // DATAMONGO-1444 - public void shouldFindOneByLastName() { + void shouldFindOneByLastName() { repository.findOneByLastname(carter.getLastname()).as(StepVerifier::create).expectNext(carter).verifyComplete(); } @Test // DATAMONGO-1444 - public void shouldFindOneByPublisherOfLastName() { + void shouldFindOneByPublisherOfLastName() { repository.findByLastname(Mono.just(carter.getLastname())).as(StepVerifier::create).expectNext(carter) .verifyComplete(); } @Test // DATAMONGO-1444 - public void shouldFindByPublisherOfLastNameIn() { + void shouldFindByPublisherOfLastNameIn() { repository.findByLastnameIn(Flux.just(carter.getLastname(), dave.getLastname())).as(StepVerifier::create) // .expectNextCount(3) // .verifyComplete(); } @Test // DATAMONGO-1444 - public void shouldFindByPublisherOfLastNameInAndAgeGreater() { + void shouldFindByPublisherOfLastNameInAndAgeGreater() { repository.findByLastnameInAndAgeGreaterThan(Flux.just(carter.getLastname(), dave.getLastname()), 41) .as(StepVerifier::create) // @@ -203,7 +202,7 @@ public void shouldFindByPublisherOfLastNameInAndAgeGreater() { } @Test // DATAMONGO-1444 - public void shouldFindUsingPublishersInStringQuery() { + void shouldFindUsingPublishersInStringQuery() { repository.findStringQuery(Flux.just("Beauford", "Matthews"), Mono.just(41)).as(StepVerifier::create) // .expectNextCount(2) // @@ -211,7 +210,7 @@ public void shouldFindUsingPublishersInStringQuery() { } @Test // DATAMONGO-1444 - public void shouldFindByLastNameAndSort() { + void shouldFindByLastNameAndSort() { repository.findByLastname("Matthews", Sort.by(ASC, "age")).as(StepVerifier::create) // .expectNext(oliver, dave) // @@ -223,7 +222,7 @@ public void shouldFindByLastNameAndSort() { } @Test // DATAMONGO-1444 - public void shouldUseTailableCursor() throws Exception { + void shouldUseTailableCursor() throws Exception { template.dropCollection(Capped.class) // .then(template.createCollection(Capped.class, // @@ -248,7 +247,7 @@ public void shouldUseTailableCursor() throws Exception { } @Test // DATAMONGO-1444 - public void shouldUseTailableCursorWithProjection() throws Exception { + void shouldUseTailableCursorWithProjection() throws Exception { template.dropCollection(Capped.class) // .then(template.createCollection(Capped.class, // @@ -279,7 +278,7 @@ public void shouldUseTailableCursorWithProjection() throws Exception { } @Test // DATAMONGO-2080 - public void shouldUseTailableCursorWithDtoProjection() { + void shouldUseTailableCursorWithDtoProjection() { template.dropCollection(Capped.class) // .then(template.createCollection(Capped.class, // @@ -292,7 +291,7 @@ public void shouldUseTailableCursorWithDtoProjection() { } @Test // DATAMONGO-1444 - public void findsPeopleByLocationWithinCircle() { + void findsPeopleByLocationWithinCircle() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -304,7 +303,7 @@ public void findsPeopleByLocationWithinCircle() { } @Test // DATAMONGO-1444 - public void findsPeopleByPageableLocationWithinCircle() { + void findsPeopleByPageableLocationWithinCircle() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -317,7 +316,7 @@ public void findsPeopleByPageableLocationWithinCircle() { } @Test // DATAMONGO-1444 - public void findsPeopleGeoresultByLocationWithinBox() { + void findsPeopleGeoresultByLocationWithinBox() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -332,7 +331,7 @@ public void findsPeopleGeoresultByLocationWithinBox() { } @Test // DATAMONGO-1444 - public void findsPeoplePageableGeoresultByLocationWithinBox() throws InterruptedException { + void findsPeoplePageableGeoresultByLocationWithinBox() throws InterruptedException { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -352,7 +351,7 @@ public void findsPeoplePageableGeoresultByLocationWithinBox() throws Interrupted } @Test // DATAMONGO-1444 - public void findsPeopleByLocationWithinBox() throws InterruptedException { + void findsPeopleByLocationWithinBox() throws InterruptedException { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); @@ -368,23 +367,23 @@ public void findsPeopleByLocationWithinBox() throws InterruptedException { } @Test // DATAMONGO-1865 - public void shouldErrorOnFindOneWithNonUniqueResult() { + void shouldErrorOnFindOneWithNonUniqueResult() { repository.findOneByLastname(dave.getLastname()).as(StepVerifier::create) .expectError(IncorrectResultSizeDataAccessException.class).verify(); } @Test // DATAMONGO-1865 - public void shouldReturnFirstFindFirstWithMoreResults() { + void shouldReturnFirstFindFirstWithMoreResults() { repository.findFirstByLastname(dave.getLastname()).as(StepVerifier::create).expectNextCount(1).verifyComplete(); } @Test // DATAMONGO-2030 - public void shouldReturnExistsBy() { + void shouldReturnExistsBy() { repository.existsByLastname(dave.getLastname()).as(StepVerifier::create).expectNext(true).verifyComplete(); } @Test // DATAMONGO-1979 - public void findAppliesAnnotatedSort() { + void findAppliesAnnotatedSort() { repository.findByAgeGreaterThan(40).collectList().as(StepVerifier::create).consumeNextWith(result -> { assertThat(result).containsSequence(carter, boyd, dave, leroi); @@ -392,7 +391,7 @@ public void findAppliesAnnotatedSort() { } @Test // DATAMONGO-1979 - public void findWithSortOverwritesAnnotatedSort() { + void findWithSortOverwritesAnnotatedSort() { repository.findByAgeGreaterThan(40, Sort.by(Direction.ASC, "age")).collectList().as(StepVerifier::create) .consumeNextWith(result -> { @@ -401,7 +400,7 @@ public void findWithSortOverwritesAnnotatedSort() { } @Test // DATAMONGO-2181 - public void considersRepositoryCollectionName() { + void considersRepositoryCollectionName() { repository.deleteAll() // .as(StepVerifier::create) // @@ -413,7 +412,7 @@ public void considersRepositoryCollectionName() { leroi.id = null; boyd.id = null; - contactRepository.saveAll(asList(leroi, boyd)) // + contactRepository.saveAll(Arrays.asList(leroi, boyd)) // .as(StepVerifier::create) // .expectNextCount(2) // .verifyComplete(); @@ -430,9 +429,9 @@ public void considersRepositoryCollectionName() { } @Test // DATAMONGO-2182 - public void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { + void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { - repository.findAll(person.id.in(asList(dave.id, carter.id))) // + repository.findAll(person.id.in(Arrays.asList(dave.id, carter.id))) // .collectList() // .as(StepVerifier::create) // .assertNext(actual -> { @@ -441,24 +440,19 @@ public void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { } @Test // DATAMONGO-2153 - public void findListOfSingleValue() { + void findListOfSingleValue() { repository.findAllLastnames() // .collectList() // .as(StepVerifier::create) // .assertNext(actual -> { - assertThat(actual) // - .contains("Lessard") // - .contains("Keys") // - .contains("Tinsley") // - .contains("Beauford") // - .contains("Moore") // - .contains("Matthews"); + assertThat(actual) + .contains("Lessard", "Keys", "Tinsley", "Beauford", "Moore", "Matthews"); }).verifyComplete(); } @Test // DATAMONGO-2153 - public void annotatedAggregationWithPlaceholderValue() { + void annotatedAggregationWithPlaceholderValue() { repository.groupByLastnameAnd("firstname") // .collectList() // @@ -470,12 +464,12 @@ public void annotatedAggregationWithPlaceholderValue() { .contains(new PersonAggregate("Tinsley", "Boyd")) // .contains(new PersonAggregate("Beauford", "Carter")) // .contains(new PersonAggregate("Moore", "Leroi")) // - .contains(new PersonAggregate("Matthews", asList("Dave", "Oliver August"))); + .contains(new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August"))); }).verifyComplete(); } @Test // DATAMONGO-2153 - public void annotatedAggregationWithSort() { + void annotatedAggregationWithSort() { repository.groupByLastnameAnd("firstname", Sort.by("lastname")) // .collectList() // @@ -486,7 +480,7 @@ public void annotatedAggregationWithSort() { new PersonAggregate("Beauford", "Carter"), // new PersonAggregate("Keys", "Alicia"), // new PersonAggregate("Lessard", "Stefan"), // - new PersonAggregate("Matthews", asList("Dave", "Oliver August")), // + new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August")), // new PersonAggregate("Moore", "Leroi"), // new PersonAggregate("Tinsley", "Boyd")); }) // @@ -494,7 +488,7 @@ public void annotatedAggregationWithSort() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithPageable() { + void annotatedAggregationWithPageable() { repository.groupByLastnameAnd("firstname", PageRequest.of(1, 2, Sort.by("lastname"))) // .collectList() // @@ -503,13 +497,13 @@ public void annotatedAggregationWithPageable() { assertThat(actual) // .containsExactly( // new PersonAggregate("Lessard", "Stefan"), // - new PersonAggregate("Matthews", asList("Dave", "Oliver August"))); + new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August"))); }) // .verifyComplete(); } @Test // DATAMONGO-2153 - public void annotatedAggregationWithSingleSimpleResult() { + void annotatedAggregationWithSingleSimpleResult() { repository.sumAge() // .as(StepVerifier::create) // @@ -518,7 +512,7 @@ public void annotatedAggregationWithSingleSimpleResult() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithAggregationResultAsReturnType() { + void annotatedAggregationWithAggregationResultAsReturnType() { repository.sumAgeAndReturnRawResult() // .as(StepVerifier::create) // @@ -527,7 +521,7 @@ public void annotatedAggregationWithAggregationResultAsReturnType() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithAggregationResultAsReturnTypeAndProjection() { + void annotatedAggregationWithAggregationResultAsReturnTypeAndProjection() { repository.sumAgeAndReturnSumWrapper() // .as(StepVerifier::create) // @@ -536,7 +530,7 @@ public void annotatedAggregationWithAggregationResultAsReturnTypeAndProjection() } @Test // DATAMONGO-2374 - public void findsWithNativeProjection() { + void findsWithNativeProjection() { repository.findDocumentById(dave.getId()) // .as(StepVerifier::create) // @@ -546,7 +540,7 @@ public void findsWithNativeProjection() { } @Test // DATAMONGO-2153 - public void annotatedAggregationWithAggregationResultAsMap() { + void annotatedAggregationWithAggregationResultAsMap() { repository.sumAgeAndReturnSumAsMap() // .as(StepVerifier::create) // @@ -556,7 +550,7 @@ public void annotatedAggregationWithAggregationResultAsMap() { } @Test // DATAMONGO-2403 - public void annotatedAggregationExtractingSimpleValueIsEmptyForEmptyDocument() { + void annotatedAggregationExtractingSimpleValueIsEmptyForEmptyDocument() { Person p = new Person("project-on-lastanme", null); repository.save(p).then().as(StepVerifier::create).verifyComplete(); @@ -567,7 +561,7 @@ public void annotatedAggregationExtractingSimpleValueIsEmptyForEmptyDocument() { } @Test // DATAMONGO-2403 - public void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { + void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { String firstname = "project-on-lastanme"; @@ -578,7 +572,7 @@ public void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { Person p3 = new Person(firstname, null); p3.setEmail("p3@example.com"); - repository.saveAll(asList(p1, p2, p3)).then().as(StepVerifier::create).verifyComplete(); + repository.saveAll(Arrays.asList(p1, p2, p3)).then().as(StepVerifier::create).verifyComplete(); repository.projectToLastnameAndRemoveId(firstname) // .as(StepVerifier::create) // @@ -586,7 +580,7 @@ public void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { } @Test // DATAMONGO-2406 - public void deleteByShouldHandleVoidResultTypeCorrectly() { + void deleteByShouldHandleVoidResultTypeCorrectly() { repository.deleteByLastname(dave.getLastname()) // .as(StepVerifier::create) // @@ -598,7 +592,7 @@ public void deleteByShouldHandleVoidResultTypeCorrectly() { } @Test // DATAMONGO-1997 - public void deleteByShouldAllowDeletedCountAsResult() { + void deleteByShouldAllowDeletedCountAsResult() { repository.deleteCountByLastname(dave.getLastname()) // .as(StepVerifier::create) // @@ -607,7 +601,7 @@ public void deleteByShouldAllowDeletedCountAsResult() { } @Test // DATAMONGO-1997 - public void deleteByShouldAllowSingleDocumentRemovalCorrectly() { + void deleteByShouldAllowSingleDocumentRemovalCorrectly() { repository.deleteSinglePersonByLastname(carter.getLastname()) // .as(StepVerifier::create) // @@ -620,9 +614,9 @@ public void deleteByShouldAllowSingleDocumentRemovalCorrectly() { } @Test // DATAMONGO-2652 - public void deleteAllById() { + void deleteAllById() { - repository.deleteAllById(asList(carter.id, dave.id)) // + repository.deleteAllById(Arrays.asList(carter.id, dave.id)) // .as(StepVerifier::create) // .verifyComplete(); @@ -731,7 +725,7 @@ static class Capped { String key; double random; - public Capped(String key, double random) { + Capped(String key, double random) { this.key = key; this.random = random; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 1455547a48..39b89c8b5c 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -61,10 +61,10 @@ * @author Jens Schauder */ @ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) -public class SimpleMongoRepositoryTests { +class SimpleMongoRepositoryTests { @Template(initialEntitySet = Person.class) // - static MongoTestTemplate template; + private static MongoTestTemplate template; private Person oliver, dave, carter, boyd, stefan, leroi, alicia; private List all; @@ -74,7 +74,7 @@ public class SimpleMongoRepositoryTests { template); @BeforeEach - public void setUp() { + void setUp() { repository.deleteAll(); @@ -90,17 +90,17 @@ public void setUp() { } @Test - public void findAllFromCustomCollectionName() { - assertThat(repository.findAll()).hasSize(all.size()); + void findAllFromCustomCollectionName() { + assertThat(repository.findAll()).hasSameSizeAs(all); } @Test - public void findOneFromCustomCollectionName() { - assertThat(repository.findById(dave.getId()).get()).isEqualTo(dave); + void findOneFromCustomCollectionName() { + assertThat(repository.findById(dave.getId())).contains(dave); } @Test - public void deleteFromCustomCollectionName() { + void deleteFromCustomCollectionName() { repository.delete(dave); @@ -108,7 +108,7 @@ public void deleteFromCustomCollectionName() { } @Test - public void deleteByIdFromCustomCollectionName() { + void deleteByIdFromCustomCollectionName() { repository.deleteById(dave.getId()); @@ -116,7 +116,7 @@ public void deleteByIdFromCustomCollectionName() { } @Test // DATAMONGO-1054 - public void shouldInsertSingle() { + void shouldInsertSingle() { String randomId = UUID.randomUUID().toString(); @@ -127,7 +127,7 @@ public void shouldInsertSingle() { } @Test // DATAMONGO-1054 - public void shouldInsertMultipleFromList() { + void shouldInsertMultipleFromList() { String randomId = UUID.randomUUID().toString(); Map idToPerson = new HashMap(); @@ -141,12 +141,12 @@ public void shouldInsertMultipleFromList() { List saved = repository.insert(persons); - assertThat(saved).hasSize(persons.size()); + assertThat(saved).hasSameSizeAs(persons); assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved); } @Test // DATAMONGO-1054 - public void shouldInsertMutlipleFromSet() { + void shouldInsertMutlipleFromSet() { String randomId = UUID.randomUUID().toString(); Map idToPerson = new HashMap(); @@ -160,12 +160,12 @@ public void shouldInsertMutlipleFromSet() { List saved = repository.insert(persons); - assertThat(saved).hasSize(persons.size()); + assertThat(saved).hasSameSizeAs(persons); assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved); } @Test // DATAMONGO-1245, DATAMONGO-1464 - public void findByExampleShouldLookUpEntriesCorrectly() { + void findByExampleShouldLookUpEntriesCorrectly() { Person sample = new Person(); sample.setLastname("Matthews"); @@ -178,7 +178,7 @@ public void findByExampleShouldLookUpEntriesCorrectly() { } @Test // DATAMONGO-1464 - public void findByExampleMultiplePagesShouldLookUpEntriesCorrectly() { + void findByExampleMultiplePagesShouldLookUpEntriesCorrectly() { Person sample = new Person(); sample.setLastname("Matthews"); @@ -191,7 +191,7 @@ public void findByExampleMultiplePagesShouldLookUpEntriesCorrectly() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldLookUpEntriesCorrectly() { + void findAllByExampleShouldLookUpEntriesCorrectly() { Person sample = new Person(); sample.setLastname("Matthews"); @@ -201,7 +201,7 @@ public void findAllByExampleShouldLookUpEntriesCorrectly() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObject() { + void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObject() { dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington")); repository.save(dave); @@ -217,7 +217,7 @@ public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObject() } @Test // DATAMONGO-1245 - public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingPartialNestedObject() { + void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingPartialNestedObject() { dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington")); repository.save(dave); @@ -233,7 +233,7 @@ public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingPartialNestedOb } @Test // DATAMONGO-1245 - public void findAllByExampleShouldNotFindEntriesWhenUsingPartialNestedObjectInStrictMode() { + void findAllByExampleShouldNotFindEntriesWhenUsingPartialNestedObjectInStrictMode() { dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington")); repository.save(dave); @@ -248,7 +248,7 @@ public void findAllByExampleShouldNotFindEntriesWhenUsingPartialNestedObjectInSt } @Test // DATAMONGO-1245 - public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObjectInStrictMode() { + void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObjectInStrictMode() { dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington")); repository.save(dave); @@ -263,7 +263,7 @@ public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObjectInS } @Test // DATAMONGO-1245 - public void findAllByExampleShouldRespectStringMatchMode() { + void findAllByExampleShouldRespectStringMatchMode() { Person sample = new Person(); sample.setLastname("Mat"); @@ -275,7 +275,7 @@ public void findAllByExampleShouldRespectStringMatchMode() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldResolveDbRefCorrectly() { + void findAllByExampleShouldResolveDbRefCorrectly() { User user = new User(); user.setId("c0nf1ux"); @@ -295,7 +295,7 @@ public void findAllByExampleShouldResolveDbRefCorrectly() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldResolveLegacyCoordinatesCorrectly() { + void findAllByExampleShouldResolveLegacyCoordinatesCorrectly() { Person megan = new Person("megan", "tarash"); megan.setLocation(new Point(41.85003D, -87.65005D)); @@ -310,7 +310,7 @@ public void findAllByExampleShouldResolveLegacyCoordinatesCorrectly() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldResolveGeoJsonCoordinatesCorrectly() { + void findAllByExampleShouldResolveGeoJsonCoordinatesCorrectly() { Person megan = new Person("megan", "tarash"); megan.setLocation(new GeoJsonPoint(41.85003D, -87.65005D)); @@ -325,7 +325,7 @@ public void findAllByExampleShouldResolveGeoJsonCoordinatesCorrectly() { } @Test // DATAMONGO-1245 - public void findAllByExampleShouldProcessInheritanceCorrectly() { + void findAllByExampleShouldProcessInheritanceCorrectly() { PersonExtended reference = new PersonExtended(); reference.setLastname("Matthews"); @@ -341,7 +341,7 @@ public void findAllByExampleShouldProcessInheritanceCorrectly() { } @Test // DATAMONGO-1245 - public void findOneByExampleShouldLookUpEntriesCorrectly() { + void findOneByExampleShouldLookUpEntriesCorrectly() { Person sample = new Person(); sample.setFirstname("Dave"); @@ -352,7 +352,7 @@ public void findOneByExampleShouldLookUpEntriesCorrectly() { } @Test // DATAMONGO-1245 - public void existsByExampleShouldLookUpEntriesCorrectly() { + void existsByExampleShouldLookUpEntriesCorrectly() { Person sample = new Person(); sample.setFirstname("Dave"); @@ -363,7 +363,7 @@ public void existsByExampleShouldLookUpEntriesCorrectly() { } @Test // DATAMONGO-1245 - public void countByExampleShouldLookUpEntriesCorrectly() { + void countByExampleShouldLookUpEntriesCorrectly() { Person sample = new Person(); sample.setLastname("Matthews"); @@ -373,7 +373,7 @@ public void countByExampleShouldLookUpEntriesCorrectly() { } @Test // DATAMONGO-1896 - public void saveAllUsesEntityCollection() { + void saveAllUsesEntityCollection() { Person first = new PersonExtended(); first.setEmail("foo@bar.com"); @@ -393,7 +393,7 @@ public void saveAllUsesEntityCollection() { @Test // DATAMONGO-2130 @EnableIfReplicaSetAvailable @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") - public void countShouldBePossibleInTransaction() { + void countShouldBePossibleInTransaction() { MongoTransactionManager txmgr = new MongoTransactionManager(template.getMongoDbFactory()); TransactionTemplate tt = new TransactionTemplate(txmgr); @@ -417,7 +417,7 @@ public void countShouldBePossibleInTransaction() { @Test // DATAMONGO-2130 @EnableIfReplicaSetAvailable @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") - public void existsShouldBePossibleInTransaction() { + void existsShouldBePossibleInTransaction() { MongoTransactionManager txmgr = new MongoTransactionManager(template.getMongoDbFactory()); TransactionTemplate tt = new TransactionTemplate(txmgr); @@ -437,14 +437,12 @@ public void existsShouldBePossibleInTransaction() { } @Test // DATAMONGO-2652 - public void deleteAllByIds() { + void deleteAllByIds() { repository.deleteAllById(asList(dave.getId(), carter.getId())); assertThat(repository.findAll()) // - .hasSize(all.size() - 2) // - .doesNotContain(dave) // - .doesNotContain(carter); + .hasSize(all.size() - 2).doesNotContain(dave, carter); } private void assertThatAllReferencePersonsWereStoredCorrectly(Map references, List saved) { From c8b64601db1d19c3039c0a7cd9472ec1b0824ac0 Mon Sep 17 00:00:00 2001 From: Yoann de Martino Date: Tue, 24 Nov 2020 10:39:46 +0100 Subject: [PATCH 0293/1381] DATAMONGO-2661 - Handle nullable types for KPropertyPath. Original pull request: #894. --- .../data/mongodb/core/query/KPropertyPath.kt | 5 +++-- .../data/mongodb/core/query/KPropertyPathTests.kt | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt index daa008af7f..d88eae4e0a 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt @@ -27,7 +27,7 @@ import kotlin.reflect.KProperty1 * @since 2.2 */ class KPropertyPath( - internal val parent: KProperty, + internal val parent: KProperty, internal val child: KProperty1 ) : KProperty by child @@ -52,7 +52,8 @@ internal fun asString(property: KProperty<*>): String { * Book::author / Author::name isEqualTo "Herman Melville" * ``` * @author Tjeu Kayim + * @author Yoann de Martino * @since 2.2 */ -operator fun KProperty.div(other: KProperty1) = +operator fun KProperty.div(other: KProperty1) = KPropertyPath(this, other) diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt index 8a13140bac..985064183e 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt @@ -93,6 +93,15 @@ class KPropertyPathTests { assertThat(property).isEqualTo("entity.book.author.name") } + @Test + fun `Convert nullable KProperty to field name`() { + class Cat(val name: String) + class Owner(val cat: Cat?) + + val property = asString(Owner::cat / Cat::name) + assertThat(property).isEqualTo("cat.name") + } + class Book(val title: String, val author: Author) class Author(val name: String) } From 65401bf4c3c0759fe1a892e40bd98e12ebc8695a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 26 Nov 2020 11:44:58 +0100 Subject: [PATCH 0294/1381] DATAMONGO-2661 - Polishing. Add ticket reference. Original pull request: #894. --- .../data/mongodb/core/query/KPropertyPathTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt index 985064183e..c52c1c8c84 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathTests.kt @@ -93,7 +93,7 @@ class KPropertyPathTests { assertThat(property).isEqualTo("entity.book.author.name") } - @Test + @Test // DATAMONGO-2661 fun `Convert nullable KProperty to field name`() { class Cat(val name: String) class Owner(val cat: Cat?) From 9d5b72db49f964da1b19037c33e4259a81d2213f Mon Sep 17 00:00:00 2001 From: abarkan Date: Tue, 10 Nov 2020 16:53:41 +0200 Subject: [PATCH 0295/1381] DATAMONGO-2659 - Allow disk use on query. Original pull request: #891. --- .../data/mongodb/core/MongoTemplate.java | 5 +++++ .../data/mongodb/core/query/Query.java | 14 ++++++++++++++ .../mongodb/core/QueryCursorPreparerUnitTests.java | 11 +++++++++++ 3 files changed, 30 insertions(+) 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 227ba00636..050d8dd876 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 @@ -156,6 +156,7 @@ * @author Michael J. Simons * @author Roman Puchkovskiy * @author Yadhukrishna S Pai + * @author Anton Barkan */ public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider { @@ -3289,6 +3290,10 @@ public FindIterable prepare(FindIterable iterable) { cursorToUse = cursorToUse.batchSize(meta.getCursorBatchSize()); } + if (meta.getAllowDiskUse() != null) { + cursorToUse = cursorToUse.allowDiskUse(meta.getAllowDiskUse()); + } + for (Meta.CursorOption option : meta.getFlags()) { switch (option) { 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 ec63ac504d..31dfd5343f 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 @@ -46,6 +46,7 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author Anton Barkan */ public class Query { @@ -372,6 +373,19 @@ public Query comment(String comment) { return this; } + /** + * Set a allowDiskUse to the query that is propagated to the profile log. + * + * @param allowDiskUse must not be {@literal null}. + * @return this. + * @see Meta#setAllowDiskUse(Boolean) + */ + public Query allowDiskUse(Boolean allowDiskUse) { + + meta.setAllowDiskUse(allowDiskUse); + return this; + } + /** * Set the number of documents to return in each response batch.
      * Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single 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 1d48242d24..2030f25ea2 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 @@ -45,6 +45,7 @@ * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch + * @author Anton Barkan */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -61,6 +62,7 @@ void setUp() { when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); when(cursor.batchSize(anyInt())).thenReturn(cursor); when(cursor.comment(anyString())).thenReturn(cursor); + when(cursor.allowDiskUse(anyBoolean())).thenReturn(cursor); when(cursor.maxTime(anyLong(), any())).thenReturn(cursor); when(cursor.hint(any())).thenReturn(cursor); when(cursor.noCursorTimeout(anyBoolean())).thenReturn(cursor); @@ -133,6 +135,15 @@ void appliesCommentCorrectly() { verify(cursor).comment("spring data"); } + @Test + void appliesAllowDiskUseCorrectly() { + + Query query = query(where("foo").is("bar")).allowDiskUse(true); + prepare(query); + + verify(cursor).allowDiskUse(true); + } + // TODO // @Test // DATAMONGO-957 // public void appliesSnapshotCorrectly() { From 3f5cc897da7c17311c8eae5d0108bc4351409c81 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 1 Dec 2020 09:41:15 +0100 Subject: [PATCH 0296/1381] DATAMONGO-2659 - Polishing. Update Javadoc to reflect find and aggregation nature. Use primitive boolean on Query.allowDiskUse to avoid nullable type usage. Update ReactiveMongoTemplate to consider allowDiskUse. Original pull request: #891. --- .../mongodb/core/ReactiveMongoTemplate.java | 4 +++ .../data/mongodb/core/query/Meta.java | 6 +++- .../data/mongodb/core/query/Query.java | 11 +++++-- .../core/QueryCursorPreparerUnitTests.java | 33 +------------------ .../core/ReactiveMongoTemplateUnitTests.java | 12 +++++++ 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 977ceb3944..d04f0805d4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -3329,6 +3329,10 @@ public FindPublisher prepare(FindPublisher findPublisher) { if (meta.getCursorBatchSize() != null) { findPublisherToUse = findPublisherToUse.batchSize(meta.getCursorBatchSize()); } + + if (meta.getAllowDiskUse() != null) { + findPublisherToUse = findPublisherToUse.allowDiskUse(meta.getAllowDiskUse()); + } } } 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 c865fef800..bf48a9f5bb 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 @@ -181,7 +181,11 @@ public Boolean getAllowDiskUse() { } /** - * Set to {@literal true}, to allow aggregation stages to write data to disk. + * Enables writing to temporary files for aggregation stages and queries. When set to {@literal true}, aggregation + * stages can write data to the {@code _tmp} subdirectory in the {@code dbPath} directory. + *

      + * Starting in MongoDB 4.2, the profiler log messages and diagnostic log messages includes a {@code usedDisk} + * indicator if any aggregation stage wrote data to temporary files due to memory restrictions. * * @param allowDiskUse use {@literal null} for server defaults. * @since 3.0 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 31dfd5343f..e509ea7a5e 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 @@ -374,13 +374,18 @@ public Query comment(String comment) { } /** - * Set a allowDiskUse to the query that is propagated to the profile log. + * Enables writing to temporary files for aggregation stages and queries. When set to {@literal true}, aggregation + * stages can write data to the {@code _tmp} subdirectory in the {@code dbPath} directory. + *

      + * Starting in MongoDB 4.2, the profiler log messages and diagnostic log messages includes a {@code usedDisk} + * indicator if any aggregation stage wrote data to temporary files due to memory restrictions. * - * @param allowDiskUse must not be {@literal null}. + * @param allowDiskUse * @return this. * @see Meta#setAllowDiskUse(Boolean) + * @since 3.2 */ - public Query allowDiskUse(Boolean allowDiskUse) { + public Query allowDiskUse(boolean allowDiskUse) { meta.setAllowDiskUse(allowDiskUse); return this; 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 2030f25ea2..975fab857d 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 @@ -96,27 +96,6 @@ void appliesDocumentHintsCorrectly() { verify(cursor).hint(new Document("age", 1)); } - // TODO - // @Test // DATAMONGO-957 - // public void doesNotApplyMetaWhenEmpty() { - // - // Query query = query(where("foo").is("bar")); - // query.setMeta(new Meta()); - // - // prepare(query); - // - // verify(cursor, never()).modifiers(any(Document.class)); - // } - - // @Test // DATAMONGO-957 - // public void appliesMaxScanCorrectly() { - // - // Query query = query(where("foo").is("bar")).maxScan(100); - // prepare(query); - // - // verify(cursor).maxScan(100); - // } - @Test // DATAMONGO-957 void appliesMaxTimeCorrectly() { @@ -135,7 +114,7 @@ void appliesCommentCorrectly() { verify(cursor).comment("spring data"); } - @Test + @Test // DATAMONGO-2659 void appliesAllowDiskUseCorrectly() { Query query = query(where("foo").is("bar")).allowDiskUse(true); @@ -144,16 +123,6 @@ void appliesAllowDiskUseCorrectly() { verify(cursor).allowDiskUse(true); } - // TODO - // @Test // DATAMONGO-957 - // public void appliesSnapshotCorrectly() { - // - // Query query = query(where("foo").is("bar")).useSnapshot(); - // prepare(query); - // - // verify(cursor).snapshot(true); - // } - @Test // DATAMONGO-1480 void appliesNoCursorTimeoutCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 916123d70b..84af574378 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -180,6 +180,7 @@ void beforeEach() { when(findPublisher.limit(anyInt())).thenReturn(findPublisher); when(findPublisher.collation(any())).thenReturn(findPublisher); when(findPublisher.first()).thenReturn(findPublisher); + when(findPublisher.allowDiskUse(anyBoolean())).thenReturn(findPublisher); when(aggregatePublisher.allowDiskUse(anyBoolean())).thenReturn(aggregatePublisher); when(aggregatePublisher.collation(any())).thenReturn(aggregatePublisher); when(aggregatePublisher.maxTime(anyLong(), any())).thenReturn(aggregatePublisher); @@ -231,6 +232,17 @@ void executeQueryShouldUseBatchSizeWhenPresent() { verify(findPublisher).batchSize(1234); } + @Test // DATAMONGO-2659 + void executeQueryShouldUseAllowDiskSizeWhenPresent() { + + when(findPublisher.batchSize(anyInt())).thenReturn(findPublisher); + + Query query = new Query().allowDiskUse(true); + template.find(query, Person.class).subscribe(); + + verify(findPublisher).allowDiskUse(true); + } + @Test // DATAMONGO-1518 void findShouldUseCollationWhenPresent() { From 8918c9718993734a6eb9c403589635d20c0cde12 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 1 Dec 2020 14:33:48 +0100 Subject: [PATCH 0297/1381] DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. Original Pull Request: #895 --- src/main/asciidoc/preface.adoc | 57 +++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/main/asciidoc/preface.adoc b/src/main/asciidoc/preface.adoc index cd1a397a39..aa3721234b 100644 --- a/src/main/asciidoc/preface.adoc +++ b/src/main/asciidoc/preface.adoc @@ -41,7 +41,62 @@ The starting point for learning about MongoDB is https://www.mongodb.org/[www.mo The Spring Data MongoDB 3.x binaries require JDK level 8.0 and above and https://spring.io/docs[Spring Framework] {springVersion} and above. -In terms of document stores, you need at least version 2.6 of https://www.mongodb.org/[MongoDB]. +In terms of document stores, you need at least version 3.6 of https://www.mongodb.org/[MongoDB], though we recommend a more recent version. + +[[compatibility.matrix]] +=== Compatibility Matrix + +The following compatibility matrix summarizes Spring Data versions to MongoDB driver/database versions. +Database versions show the highest supported server version that pass the Spring Data test suite. +You can use newer server versions unless your application uses functionality that is affected by <>. + +[cols="h,m,m,m", options="header"] +|=== + +|Spring Data Release Train +|Spring Data MongoDB +|Driver Version +|Server Version + +|2021.0 +|3.2.x +|4.1.x +|4.4.x + +|2020.0 +|3.1.x +|4.1.x +|4.4.x + +|Neumann +|3.0.x +|4.0.x +|4.4.x + +|Moore +|2.2.x +|3.11.x/Reactive Streams 1.12.x +|4.2.x + +|Lovelace +|2.1.x +|3.8.x/Reactive Streams 1.9.x +|4.0.x + +|=== + +[[compatibility.changes]] +[[compatibility.changes-4.4]] +==== Relevant Changes in MongoDB 4.4 + +* Fields list must not contain text search score property when no `$text` criteria present. See also https://docs.mongodb.com/manual/reference/operator/query/text/[`$text` operator] +* Sort must not be an empty document when running map reduce. + +[[compatibility.changes-4.2]] +==== Relevant Changes in MongoDB 4.2 + +* Removal of `geoNear` command. See also https://docs.mongodb.com/manual/release-notes/4.2-compatibility/#remove-support-for-the-geonear-command[Removal of `geoNear`] +* Removal of `eval` command. See also https://docs.mongodb.com/manual/release-notes/4.2-compatibility/#remove-support-for-the-eval-command[Removal of `eval`] [[get-started:help]] == Additional Help Resources From fece1e99cb610fb34a0eb793623d79221b9e0c29 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 09:37:03 +0100 Subject: [PATCH 0298/1381] DATAMONGO-2646 - Updated changelog. --- src/main/resources/changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index e78eff57bd..c42593deb4 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,12 @@ Spring Data MongoDB Changelog ============================= +Changes in version 2.2.12.RELEASE (2020-12-09) +---------------------------------------------- +* DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. +* DATAMONGO-2646 - Release 2.2.12 (Moore SR12). + + Changes in version 3.1.1 (2020-11-11) ------------------------------------- * DATAMONGO-2648 - Release 3.1.1 (2020.0.1). @@ -3224,5 +3230,6 @@ Repository + From 8dea0712706902caccfadffb78130c5b74490a76 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 11:15:51 +0100 Subject: [PATCH 0299/1381] DATAMONGO-2647 - Updated changelog. --- src/main/resources/changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index c42593deb4..22b23b85ea 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,14 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.0.6.RELEASE (2020-12-09) +--------------------------------------------- +* DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. +* DATAMONGO-2661 - Handle nullable types for KPropertyPath. +* DATAMONGO-2647 - Release 3.0.6 (Neumann SR6). +* DATAMONGO-2644 - Invalid reference '_id'! Error In spring data mongodb. + + Changes in version 2.2.12.RELEASE (2020-12-09) ---------------------------------------------- * DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. @@ -3231,5 +3239,6 @@ Repository + From d605a227fc4f9413880a5f99d35651941f440d20 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 15:21:25 +0100 Subject: [PATCH 0300/1381] DATAMONGO-2649 - Updated changelog. --- src/main/resources/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 22b23b85ea..57960a3b8b 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,17 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.2.0-M1 (2020-12-09) +---------------------------------------- +* DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. +* DATAMONGO-2661 - Handle nullable types for KPropertyPath. +* DATAMONGO-2659 - Allow disk use on Query. +* DATAMONGO-2652 - Implement CrudRepository.delete(Iterable ids). +* DATAMONGO-2649 - Release 3.2 M1 (2021.0.0). +* DATAMONGO-2644 - Invalid reference '_id'! Error In spring data mongodb. +* DATAMONGO-2635 - Enums Don't Properly Serialize In Aggregation Pipeline Facet. + + Changes in version 3.0.6.RELEASE (2020-12-09) --------------------------------------------- * DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. @@ -3240,5 +3251,6 @@ Repository + From 1e84f379b270e72739698d6ee7010bfcea7df3b7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 15:21:28 +0100 Subject: [PATCH 0301/1381] DATAMONGO-2649 - Prepare 3.2 M1 (2021.0.0). --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 99721676cb..4253bc345f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.5.0-SNAPSHOT + 2.5.0-M1 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.5.0-SNAPSHOT + 2.5.0-M1 4.1.1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index fcb471e1ff..d8f896898e 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.1 GA (2020.0.0) +Spring Data MongoDB 3.2 M1 (2021.0.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -20,3 +20,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 39825363013da218c88a02a525fb274f6a5b9404 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 15:21:55 +0100 Subject: [PATCH 0302/1381] DATAMONGO-2649 - Release version 3.2 M1 (2021.0.0). --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 4253bc345f..7585734348 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-M1 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index f0fbb601c8..f14800a6c2 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-M1 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 1a17321782..137028450d 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-M1 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 0248517caf..67195e64a5 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-M1 ../pom.xml From b5d54851960820182b4dd1c4decce6fd0006507e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 15:32:15 +0100 Subject: [PATCH 0303/1381] DATAMONGO-2649 - Prepare next development iteration. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 7585734348..4253bc345f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-M1 + 3.2.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index f14800a6c2..f0fbb601c8 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-M1 + 3.2.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 137028450d..1a17321782 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-M1 + 3.2.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 67195e64a5..0248517caf 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-M1 + 3.2.0-SNAPSHOT ../pom.xml From d1c6b0cd193c40e15bf8f1e5ea8eecdda693c593 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 15:32:19 +0100 Subject: [PATCH 0304/1381] DATAMONGO-2649 - After release cleanups. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 4253bc345f..99721676cb 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.5.0-M1 + 2.5.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.5.0-M1 + 2.5.0-SNAPSHOT 4.1.1 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From c66ffeaa09400b3ec7455890edd9984609853260 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Dec 2020 16:00:49 +0100 Subject: [PATCH 0305/1381] DATAMONGO-2653 - Updated changelog. --- src/main/resources/changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 57960a3b8b..5c5f98761d 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,13 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.2 (2020-12-09) +------------------------------------- +* DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. +* DATAMONGO-2661 - Handle nullable types for KPropertyPath. +* DATAMONGO-2653 - Release 3.1.2 (2020.0.2). + + Changes in version 3.2.0-M1 (2020-12-09) ---------------------------------------- * DATAMONGO-2663 - Document Spring Data to MongoDB compatibility. @@ -3252,5 +3259,6 @@ Repository + From b7310fd1aec43b8322842c471d77e27139eb20bd Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Mon, 14 Dec 2020 16:43:15 -0600 Subject: [PATCH 0306/1381] DATAMONGO-2665 - Use Docker hub credentials for all CI jobs, --- Jenkinsfile | 153 +++++++++++++++++++++++++++------------------------- pom.xml | 6 ++- 2 files changed, 85 insertions(+), 74 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4f1379af27..27d5a07f77 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -73,21 +73,22 @@ pipeline { } } agent { - docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.2.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } + label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('springci/spring-data-openjdk8-with-mongodb-4.2.0:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + } + } + } } } @@ -101,61 +102,64 @@ pipeline { parallel { stage("test: mongodb 4.0 (jdk8)") { agent { - docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } + label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('springci/spring-data-openjdk8-with-mongodb-4.0:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + } + } + } } } stage("test: mongodb 4.2 (jdk8)") { agent { - docker { - image 'springci/spring-data-openjdk8-with-mongodb-4.2.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } + label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('springci/spring-data-openjdk8-with-mongodb-4.2.0:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + } + } + } } } stage("test: baseline (jdk15)") { agent { - docker { - image 'springci/spring-data-openjdk15-with-mongodb-4.2.0:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } + label 'data' } options { timeout(time: 30, unit: 'MINUTES') } steps { - sh 'rm -rf ?' - sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' - sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' - sh 'sleep 10' - sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' - sh 'sleep 15' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('springci/spring-data-openjdk15-with-mongodb-4.2.0:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pjava11 clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + } + } + } } } } @@ -169,11 +173,7 @@ pipeline { } } agent { - docker { - image 'adoptopenjdk/openjdk8:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } + label 'data' } options { timeout(time: 20, unit: 'MINUTES') } @@ -182,15 +182,20 @@ pipeline { } steps { - sh 'rm -rf ?' - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory ' + - '-Dartifactory.server=https://repo.spring.io ' + - "-Dartifactory.username=${ARTIFACTORY_USR} " + - "-Dartifactory.password=${ARTIFACTORY_PSW} " + - "-Dartifactory.staging-repository=libs-snapshot-local " + - "-Dartifactory.build-name=spring-data-mongodb " + - "-Dartifactory.build-number=${BUILD_NUMBER} " + - '-Dmaven.test.skip=true clean deploy -U -B' + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory ' + + '-Dartifactory.server=https://repo.spring.io ' + + "-Dartifactory.username=${ARTIFACTORY_USR} " + + "-Dartifactory.password=${ARTIFACTORY_PSW} " + + "-Dartifactory.staging-repository=libs-snapshot-local " + + "-Dartifactory.build-name=spring-data-mongodb " + + "-Dartifactory.build-number=${BUILD_NUMBER} " + + '-Dmaven.test.skip=true clean deploy -U -B' + } + } + } } } @@ -199,11 +204,7 @@ pipeline { branch 'master' } agent { - docker { - image 'adoptopenjdk/openjdk8:latest' - label 'data' - args '-v $HOME:/tmp/jenkins-home' - } + label 'data' } options { timeout(time: 20, unit: 'MINUTES') } @@ -212,12 +213,18 @@ pipeline { } steps { - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,distribute ' + - '-Dartifactory.server=https://repo.spring.io ' + - "-Dartifactory.username=${ARTIFACTORY_USR} " + - "-Dartifactory.password=${ARTIFACTORY_PSW} " + - "-Dartifactory.distribution-repository=temp-private-local " + - '-Dmaven.test.skip=true clean deploy -U -B' + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,distribute ' + + '-Dartifactory.server=https://repo.spring.io ' + + "-Dartifactory.username=${ARTIFACTORY_USR} " + + "-Dartifactory.password=${ARTIFACTORY_PSW} " + + "-Dartifactory.distribution-repository=temp-private-local " + + '-Dmaven.test.skip=true clean deploy -U -B' + } + } + } } } } diff --git a/pom.xml b/pom.xml index 99721676cb..10c1adf1bf 100644 --- a/pom.xml +++ b/pom.xml @@ -158,7 +158,11 @@ spring-libs-milestone https://repo.spring.io/libs-milestone - + + bintray-plugins + bintray-plugins + https://jcenter.bintray.com + From 4d10962d128e4894fba2dddb28ad6af8f90bf37f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 31 Dec 2020 09:16:46 +0100 Subject: [PATCH 0307/1381] #3529 - Add GitHub actions workflow for issue management. --- .github/PULL_REQUEST_TEMPLATE.md | 1 - .github/workflows/project.yml | 47 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/project.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6c5d559a8a..e8f632af23 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,7 +6,6 @@ Make sure that: --> - [ ] You have read the [Spring Data contribution guidelines](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc). -- [ ] There is a ticket in the bug tracker for the project in our [JIRA](https://jira.spring.io/browse/DATAMONGO). - [ ] You use the code formatters provided [here](https://github.com/spring-projects/spring-data-build/tree/master/etc/ide) and have them applied to your changes. Don’t submit any formatting related changes. - [ ] You submit test cases (unit or integration tests) that back your changes. - [ ] You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only). diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml new file mode 100644 index 0000000000..cad9723a8e --- /dev/null +++ b/.github/workflows/project.yml @@ -0,0 +1,47 @@ +# GitHub Actions to automate GitHub issues for Spring Data Project Management + +name: Spring Data GitHub Issues + +on: + issues: + types: [opened, edited, reopened] + issue_comment: + types: [created] + pull_request_target: + types: [opened, edited, reopened] + +jobs: + Inbox: + runs-on: ubuntu-latest + if: github.repository_owner == 'spring-projects' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request == null + steps: + - name: Create or Update Issue Card + uses: peter-evans/create-or-update-project-card@v1.1.2 + with: + project-name: 'Spring Data' + column-name: 'Inbox' + project-location: 'spring-projects' + token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }} + Pull-Request: + runs-on: ubuntu-latest + if: github.repository_owner == 'spring-projects' && (github.event.action == 'opened' || github.event.action == 'reopened') && github.event.pull_request != null + steps: + - name: Create or Update Pull Request Card + uses: peter-evans/create-or-update-project-card@v1.1.2 + with: + project-name: 'Spring Data' + column-name: 'Review pending' + project-location: 'spring-projects' + issue-number: ${{ github.event.pull_request.number }} + token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }} + Feedback-Provided: + runs-on: ubuntu-latest + if: github.repository_owner == 'spring-projects' && github.event.action == 'created' && contains(join(github.event.issue.labels.*.name, ', '), 'waiting-for-feedback') + steps: + - name: Update Project Card + uses: peter-evans/create-or-update-project-card@v1.1.2 + with: + project-name: 'Spring Data' + column-name: 'Feedback provided' + project-location: 'spring-projects' + token: ${{ secrets.GH_ISSUES_TOKEN_SPRING_DATA }} From b56e17e0eb68243e68bfb1ab57e190f9af368f16 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 16 Dec 2020 09:44:43 +0100 Subject: [PATCH 0308/1381] DATAMONGO-2671 - Fix dateFromParts millisecond field name. Use millisecond instead of milliseconds field name. Related to: https://jira.mongodb.org/browse/DOCS-10652 Original pull request: #897. --- .../core/aggregation/DateOperators.java | 60 +++++++++++++++---- .../core/spel/MethodReferenceNode.java | 4 +- .../ProjectionOperationUnitTests.java | 12 ++-- .../SpelExpressionTransformerUnitTests.java | 8 +-- 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index 6305961c41..d912a3289c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -1829,34 +1829,74 @@ default T secondOf(AggregationExpression expression) { } /** - * Set the {@literal milliseconds} to the given value which must resolve to a value in range {@code 0 - 999}. Can be + * Set the {@literal millisecond} to the given value which must resolve to a value in range {@code 0 - 999}. Can be * a simple value, {@link Field field reference} or {@link AggregationExpression expression}. * - * @param milliseconds must not be {@literal null}. + * @param millisecond must not be {@literal null}. * @return new instance. - * @throws IllegalArgumentException if given {@literal milliseconds} is {@literal null} + * @throws IllegalArgumentException if given {@literal millisecond} is {@literal null} + * @deprecated use {@link #millisecond(Object)} instead. */ - T milliseconds(Object milliseconds); + @Deprecated + default T milliseconds(Object millisecond) { + return millisecond(millisecond); + } + + /** + * Set the {@literal millisecond} to the given value which must resolve to a value in range {@code 0 - 999}. Can be + * a simple value, {@link Field field reference} or {@link AggregationExpression expression}. + * + * @param millisecond must not be {@literal null}. + * @return new instance. + * @throws IllegalArgumentException if given {@literal millisecond} is {@literal null} + */ + T millisecond(Object millisecond); /** - * Set the {@literal milliseconds} to the value resolved by following the given {@link Field field reference}. + * Set the {@literal millisecond} to the value resolved by following the given {@link Field field reference}. * * @param fieldReference must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}. + * @deprecated use {@link #millisecondOf(String)} instead. */ + @Deprecated default T millisecondsOf(String fieldReference) { + return millisecondOf(fieldReference); + } + + /** + * Set the {@literal millisecond} to the value resolved by following the given {@link Field field reference}. + * + * @param fieldReference must not be {@literal null}. + * @return new instance. + * @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}. + */ + default T millisecondOf(String fieldReference) { return milliseconds(Fields.field(fieldReference)); } /** - * Set the {@literal milliseconds} to the result of the given {@link AggregationExpression expression}. + * Set the {@literal millisecond} to the result of the given {@link AggregationExpression expression}. * * @param expression must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal expression} is {@literal null}. + * @deprecated use {@link #millisecondOf(AggregationExpression)} instead. */ + @Deprecated default T millisecondsOf(AggregationExpression expression) { + return millisecondOf(expression); + } + + /** + * Set the {@literal milliseconds} to the result of the given {@link AggregationExpression expression}. + * + * @param expression must not be {@literal null}. + * @return new instance. + * @throws IllegalArgumentException if given {@literal expression} is {@literal null}. + */ + default T millisecondOf(AggregationExpression expression) { return milliseconds(expression); } } @@ -1971,8 +2011,8 @@ public DateFromParts second(Object second) { } @Override - public DateFromParts milliseconds(Object milliseconds) { - return new DateFromParts(append("milliseconds", milliseconds)); + public DateFromParts millisecond(Object millisecond) { + return new DateFromParts(append("millisecond", millisecond)); } /** @@ -2147,8 +2187,8 @@ public IsoDateFromParts second(Object second) { } @Override - public IsoDateFromParts milliseconds(Object milliseconds) { - return new IsoDateFromParts(append("milliseconds", milliseconds)); + public IsoDateFromParts millisecond(Object millisecond) { + return new IsoDateFromParts(append("millisecond", millisecond)); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 8bf6a8f98b..92fb194769 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -145,9 +145,9 @@ public class MethodReferenceNode extends ExpressionNode { map.put("dateFromString", mapArgRef().forOperator("$dateFromString") // .mappingParametersTo("dateString", "format", "timezone", "onError", "onNull")); map.put("dateFromParts", mapArgRef().forOperator("$dateFromParts").mappingParametersTo("year", "month", "day", - "hour", "minute", "second", "milliseconds", "timezone")); + "hour", "minute", "second", "millisecond", "timezone")); map.put("isoDateFromParts", mapArgRef().forOperator("$dateFromParts").mappingParametersTo("isoWeekYear", "isoWeek", - "isoDayOfWeek", "hour", "minute", "second", "milliseconds", "timezone")); + "isoDayOfWeek", "hour", "minute", "second", "millisecond", "timezone")); map.put("dateToParts", mapArgRef().forOperator("$dateToParts") // .mappingParametersTo("date", "timezone", "iso8601")); map.put("isoDayOfWeek", singleArgRef().forOperator("$isoDayOfWeek")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index 5e7dbbcc04..e7c37474b3 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -1990,15 +1990,15 @@ public void shouldRenderDateFromPartsWithJustTheYear() { assertThat(agg).isEqualTo(Document.parse("{ $project : { newDate: { $dateFromParts: { year : 2018 } } } }")); } - @Test // DATAMONGO-1834 + @Test // DATAMONGO-1834, DATAMONGO-2671 public void shouldRenderDateFromParts() { Document agg = project() - .and(DateOperators.dateFromParts().year(2018).month(3).day(23).hour(14).minute(25).second(10).milliseconds(2)) + .and(DateOperators.dateFromParts().year(2018).month(3).day(23).hour(14).minute(25).second(10).millisecond(2)) .as("newDate").toDocument(Aggregation.DEFAULT_CONTEXT); assertThat(agg).isEqualTo(Document.parse( - "{ $project : { newDate: { $dateFromParts: { year : 2018, month : 3, day : 23, hour : 14, minute : 25, second : 10, milliseconds : 2 } } } }")); + "{ $project : { newDate: { $dateFromParts: { year : 2018, month : 3, day : 23, hour : 14, minute : 25, second : 10, millisecond : 2 } } } }")); } @Test // DATAMONGO-1834 @@ -2021,14 +2021,14 @@ public void shouldRenderIsoDateFromPartsWithJustTheYear() { assertThat(agg).isEqualTo(Document.parse("{ $project : { newDate: { $dateFromParts: { isoWeekYear : 2018 } } } }")); } - @Test // DATAMONGO-1834 + @Test // DATAMONGO-1834, DATAMONGO-2671 public void shouldRenderIsoDateFromParts() { Document agg = project().and(DateOperators.dateFromParts().isoWeekYear(2018).isoWeek(12).isoDayOfWeek(5).hour(14) - .minute(30).second(42).milliseconds(2)).as("newDate").toDocument(Aggregation.DEFAULT_CONTEXT); + .minute(30).second(42).millisecond(2)).as("newDate").toDocument(Aggregation.DEFAULT_CONTEXT); assertThat(agg).isEqualTo(Document.parse( - "{ $project : { newDate: { $dateFromParts: { isoWeekYear : 2018, isoWeek : 12, isoDayOfWeek : 5, hour : 14, minute : 30, second : 42, milliseconds : 2 } } } }")); + "{ $project : { newDate: { $dateFromParts: { isoWeekYear : 2018, isoWeek : 12, isoDayOfWeek : 5, hour : 14, minute : 30, second : 42, millisecond : 2 } } } }")); } @Test // DATAMONGO-1834 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index b4f97ce988..755364e6b7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -902,18 +902,18 @@ public void shouldRenderDateFromStringWithFormatTimezoneOnErrorAndOnNull() { "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1, \"onNull\" : -2}}")); } - @Test // DATAMONGO-2077 + @Test // DATAMONGO-2077, DATAMONGO-2671 public void shouldRenderDateFromParts() { assertThat(transform("dateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo(Document.parse( - "{ \"$dateFromParts\" : {\"year\" : \"$y\", \"month\" : \"$m\", \"day\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"milliseconds\" : \"$ms\", \"timezone\" : \"UTC\"}}")); + "{ \"$dateFromParts\" : {\"year\" : \"$y\", \"month\" : \"$m\", \"day\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}")); } - @Test // DATAMONGO-2077 + @Test // DATAMONGO-2077, DATAMONGO-2671 public void shouldRenderIsoDateFromParts() { assertThat(transform("isoDateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo(Document.parse( - "{ \"$dateFromParts\" : {\"isoWeekYear\" : \"$y\", \"isoWeek\" : \"$m\", \"isoDayOfWeek\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"milliseconds\" : \"$ms\", \"timezone\" : \"UTC\"}}")); + "{ \"$dateFromParts\" : {\"isoWeekYear\" : \"$y\", \"isoWeek\" : \"$m\", \"isoDayOfWeek\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}")); } @Test // DATAMONGO-2077 From 3277673e397c8d4a2354d42fcd02b39a85c50793 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 11 Jan 2021 12:12:20 +0100 Subject: [PATCH 0309/1381] DATAMONGO-2671 - Polishing. Fix copyright header. Add since tags. Original pull request: #897. --- .../data/mongodb/core/aggregation/DateOperators.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index d912a3289c..15f10f7d6c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018. the original author or authors. + * Copyright 2016-2021 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. @@ -1835,7 +1835,7 @@ default T secondOf(AggregationExpression expression) { * @param millisecond must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal millisecond} is {@literal null} - * @deprecated use {@link #millisecond(Object)} instead. + * @deprecated since 3.2, use {@link #millisecond(Object)} instead. */ @Deprecated default T milliseconds(Object millisecond) { @@ -1849,6 +1849,7 @@ default T milliseconds(Object millisecond) { * @param millisecond must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal millisecond} is {@literal null} + * @since 3.2 */ T millisecond(Object millisecond); @@ -1858,7 +1859,7 @@ default T milliseconds(Object millisecond) { * @param fieldReference must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}. - * @deprecated use {@link #millisecondOf(String)} instead. + * @deprecated since 3.2,use {@link #millisecondOf(String)} instead. */ @Deprecated default T millisecondsOf(String fieldReference) { @@ -1871,6 +1872,7 @@ default T millisecondsOf(String fieldReference) { * @param fieldReference must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal fieldReference} is {@literal null}. + * @since 3.2 */ default T millisecondOf(String fieldReference) { return milliseconds(Fields.field(fieldReference)); @@ -1882,7 +1884,7 @@ default T millisecondOf(String fieldReference) { * @param expression must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal expression} is {@literal null}. - * @deprecated use {@link #millisecondOf(AggregationExpression)} instead. + * @deprecated since 3.2, use {@link #millisecondOf(AggregationExpression)} instead. */ @Deprecated default T millisecondsOf(AggregationExpression expression) { @@ -1895,6 +1897,7 @@ default T millisecondsOf(AggregationExpression expression) { * @param expression must not be {@literal null}. * @return new instance. * @throws IllegalArgumentException if given {@literal expression} is {@literal null}. + * @since 3.2 */ default T millisecondOf(AggregationExpression expression) { return milliseconds(expression); From b8298ed23dd038e891f824bebcdf38acadedab27 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 11 Jan 2021 12:14:06 +0100 Subject: [PATCH 0310/1381] DATAMONGO-2671 - Polishing. Fix copyright header. Original pull request: #897. --- .../aggregation/AccumulatorOperators.java | 2 +- .../core/aggregation/ArithmeticOperators.java | 44 +++++++++---------- .../core/aggregation/BooleanOperators.java | 2 +- .../core/aggregation/DataTypeOperators.java | 2 +- .../core/aggregation/LiteralOperators.java | 4 +- ...ExpressionAggregationOperationContext.java | 2 +- .../core/aggregation/SetOperators.java | 2 +- .../core/aggregation/VariableOperators.java | 2 +- .../core/index/PartialIndexFilter.java | 2 +- .../mongodb/core/spel/NotOperatorNode.java | 2 +- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java index c9a5a73c3a..6698b932f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 2fbc64304e..6053f3ae1b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. @@ -644,7 +644,7 @@ public static Add valueOf(Number value) { /** * Add the value stored at the given field. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Add}. */ @@ -656,7 +656,7 @@ public Add add(String fieldReference) { /** * Add the evaluation result of the given {@link AggregationExpression}. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Add}. */ @@ -668,7 +668,7 @@ public Add add(AggregationExpression expression) { /** * Add the given value. - * + * * @param value must not be {@literal null}. * @return new instance of {@link Add}. */ @@ -784,7 +784,7 @@ public static Divide valueOf(Number value) { /** * Divide by the value stored at the given field. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Divide}. */ @@ -796,7 +796,7 @@ public Divide divideBy(String fieldReference) { /** * Divide by the evaluation results of the given {@link AggregationExpression}. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Divide}. */ @@ -808,7 +808,7 @@ public Divide divideBy(AggregationExpression expression) { /** * Divide by the given value. - * + * * @param value must not be {@literal null}. * @return new instance of {@link Divide}. */ @@ -1030,7 +1030,7 @@ public static Log valueOf(Number value) { /** * Use the value stored at the given field as log base. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Log}. */ @@ -1042,7 +1042,7 @@ public Log log(String fieldReference) { /** * Use the evaluated value of the given {@link AggregationExpression} as log base. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Log}. */ @@ -1054,7 +1054,7 @@ public Log log(AggregationExpression expression) { /** * Use the given value as log base. - * + * * @param base must not be {@literal null}. * @return new instance of {@link Log}. */ @@ -1170,7 +1170,7 @@ public static Mod valueOf(Number value) { /** * Use the value stored at the given field as mod base. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Mod}. */ @@ -1182,7 +1182,7 @@ public Mod mod(String fieldReference) { /** * Use evaluated value of the given {@link AggregationExpression} as mod base. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Mod}. */ @@ -1194,7 +1194,7 @@ public Mod mod(AggregationExpression expression) { /** * Use the given value as mod base. - * + * * @param base must not be {@literal null}. * @return new instance of {@link Mod}. */ @@ -1257,7 +1257,7 @@ public static Multiply valueOf(Number value) { /** * Multiply by the value stored at the given field. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Multiply}. */ @@ -1269,7 +1269,7 @@ public Multiply multiplyBy(String fieldReference) { /** * Multiply by the evaluated value of the given {@link AggregationExpression}. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Multiply}. */ @@ -1281,7 +1281,7 @@ public Multiply multiplyBy(AggregationExpression expression) { /** * Multiply by the given value. - * + * * @param value must not be {@literal null}. * @return new instance of {@link Multiply}. */ @@ -1344,7 +1344,7 @@ public static Pow valueOf(Number value) { /** * Pow by the value stored at the given field. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Pow}. */ @@ -1356,7 +1356,7 @@ public Pow pow(String fieldReference) { /** * Pow by the evaluated value of the given {@link AggregationExpression}. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Pow}. */ @@ -1368,7 +1368,7 @@ public Pow pow(AggregationExpression expression) { /** * Pow by the given value. - * + * * @param value must not be {@literal null}. * @return new instance of {@link Pow}. */ @@ -1484,7 +1484,7 @@ public static Subtract valueOf(Number value) { /** * Subtract the value stored at the given field. - * + * * @param fieldReference must not be {@literal null}. * @return new instance of {@link Pow}. */ @@ -1496,7 +1496,7 @@ public Subtract subtract(String fieldReference) { /** * Subtract the evaluated value of the given {@link AggregationExpression}. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link Pow}. */ @@ -1508,7 +1508,7 @@ public Subtract subtract(AggregationExpression expression) { /** * Subtract the given value. - * + * * @param value must not be {@literal null}. * @return new instance of {@link Pow}. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java index b651a89616..eaee42d96e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BooleanOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java index 9ce1f314fb..fbc49ef080 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DataTypeOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java index 062f823e37..f692008de6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LiteralOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. @@ -76,7 +76,7 @@ private Literal(Object value) { super(value); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AbstractAggregationExpression#getMongoMethod() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/NestedDelegatingExpressionAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/NestedDelegatingExpressionAggregationOperationContext.java index 1aa4432eea..50afa52909 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/NestedDelegatingExpressionAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/NestedDelegatingExpressionAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java index 874ce71893..395b864e24 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java index a89ba122f3..781a8794f9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/VariableOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java index 66cdf7a80a..a0ce869bf9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/NotOperatorNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/NotOperatorNode.java index 97df6afee0..7a93a1f17f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/NotOperatorNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/NotOperatorNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2016. the original author or authors. + * Copyright 2016-2021 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. From 19e62787b846dd79fa921d9ed6652b91849e323e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 17 Dec 2020 13:04:07 +0100 Subject: [PATCH 0311/1381] DATAMONGO-2651 - Support $accumulator in GroupOperationBuilder. Original pull request: #898. --- .../core/aggregation/GroupOperation.java | 27 ++++++++++++++++--- .../aggregation/GroupOperationUnitTests.java | 15 ++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index 8f586fd754..b58ec4b24d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -23,6 +23,7 @@ import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference; +import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -375,6 +376,17 @@ public GroupOperationBuilder stdDevPop(AggregationExpression expr) { return newBuilder(GroupOps.STD_DEV_POP, null, expr); } + /** + * Generates an {@link GroupOperationBuilder} for an {@code $accumulator}-expression. + * + * @param accumulator must not be {@literal null}. + * @return never {@literal null}. + * @since 1.10 + */ + public GroupOperationBuilder accumulate(Accumulator accumulator) { + return new GroupOperationBuilder(this, new Operation(accumulator)); + } + private GroupOperationBuilder newBuilder(Keyword keyword, @Nullable String reference, @Nullable Object value) { return new GroupOperationBuilder(this, new Operation(keyword, null, reference, value)); } @@ -465,12 +477,16 @@ public String toString() { static class Operation implements AggregationOperation { - private final Keyword op; + private final @Nullable Keyword op; private final @Nullable String key; private final @Nullable String reference; private final @Nullable Object value; - public Operation(Keyword op, @Nullable String key, @Nullable String reference, @Nullable Object value) { + Operation(AggregationExpression expression) { + this(null, null, null, expression); + } + + public Operation(@Nullable Keyword op, @Nullable String key, @Nullable String reference, @Nullable Object value) { this.op = op; this.key = key; @@ -487,7 +503,12 @@ public ExposedField asField() { } public Document toDocument(AggregationOperationContext context) { - return new Document(key, new Document(op.toString(), getValue(context))); + + Object value = getValue(context); + if(op == null && value instanceof Document) { + return new Document(key, value); + } + return new Document(key, new Document(op.toString(), value)); } public Object getValue(AggregationOperationContext context) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java index 6239b3d10f..3340e8119b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java @@ -23,7 +23,6 @@ import org.bson.Document; import org.junit.jupiter.api.Test; - import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.query.Criteria; @@ -241,6 +240,20 @@ public void sumWithNullExpressionShouldThrowException() { .isThrownBy(() -> Aggregation.group("username").sum((AggregationExpression) null)); } + @Test // DATAMONGO-2651 + void accumulatorShouldBeAllowedOnGroupOperation() { + + GroupOperation groupOperation = Aggregation.group("id") + .accumulate( + ScriptOperators.accumulatorBuilder().init("inti").accumulate("acc").merge("merge").finalize("finalize")) + .as("accumulated-value"); + + Document groupClause = extractDocumentFromGroupOperation(groupOperation); + Document accumulatedValue = DocumentTestUtils.getAsDocument(groupClause, "accumulated-value"); + + assertThat(accumulatedValue.get("$accumulator")).isNotNull(); + } + private Document extractDocumentFromGroupOperation(GroupOperation groupOperation) { Document document = groupOperation.toDocument(Aggregation.DEFAULT_CONTEXT); Document groupClause = DocumentTestUtils.getAsDocument(document, "$group"); From 8b0ecf17c404506737c44d4647c4a89f5f7451f5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 11 Jan 2021 14:48:54 +0100 Subject: [PATCH 0312/1381] DATAMONGO-2651 - Polishing. Update since tag. Reduce test class/method visibility, update license headers. Original pull request: #898. --- .../core/aggregation/GroupOperation.java | 6 +- .../aggregation/GroupOperationUnitTests.java | 73 ++++++++++--------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index b58ec4b24d..ee129154dd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -381,7 +381,7 @@ public GroupOperationBuilder stdDevPop(AggregationExpression expr) { * * @param accumulator must not be {@literal null}. * @return never {@literal null}. - * @since 1.10 + * @since 3.2 */ public GroupOperationBuilder accumulate(Accumulator accumulator) { return new GroupOperationBuilder(this, new Operation(accumulator)); @@ -444,7 +444,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), operationObject); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java index 3340e8119b..e63aa9ca80 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GroupOperationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -20,6 +20,7 @@ import static org.springframework.data.mongodb.core.aggregation.Fields.*; import java.util.Arrays; +import java.util.Collections; import org.bson.Document; import org.junit.jupiter.api.Test; @@ -33,15 +34,15 @@ * @author Thomas Darimont * @author Gustavo de Geus */ -public class GroupOperationUnitTests { +class GroupOperationUnitTests { @Test - public void rejectsNullFields() { + void rejectsNullFields() { assertThatIllegalArgumentException().isThrownBy(() -> new GroupOperation((Fields) null)); } @Test // DATAMONGO-759 - public void groupOperationWithNoGroupIdFieldsShouldGenerateNullAsGroupId() { + void groupOperationWithNoGroupIdFieldsShouldGenerateNullAsGroupId() { GroupOperation operation = new GroupOperation(Fields.from()); ExposedFields fields = operation.getFields(); @@ -53,7 +54,7 @@ public void groupOperationWithNoGroupIdFieldsShouldGenerateNullAsGroupId() { } @Test // DATAMONGO-759 - public void groupOperationWithNoGroupIdFieldsButAdditionalFieldsShouldGenerateNullAsGroupId() { + void groupOperationWithNoGroupIdFieldsButAdditionalFieldsShouldGenerateNullAsGroupId() { GroupOperation operation = new GroupOperation(Fields.from()).count().as("cnt").last("foo").as("foo"); ExposedFields fields = operation.getFields(); @@ -67,62 +68,62 @@ public void groupOperationWithNoGroupIdFieldsButAdditionalFieldsShouldGenerateNu } @Test - public void createsGroupOperationWithSingleField() { + void createsGroupOperationWithSingleField() { GroupOperation operation = new GroupOperation(fields("a")); Document groupClause = extractDocumentFromGroupOperation(operation); - assertThat(groupClause.get(UNDERSCORE_ID)).isEqualTo((Object) "$a"); + assertThat(groupClause).containsEntry(UNDERSCORE_ID, "$a"); } @Test - public void createsGroupOperationWithMultipleFields() { + void createsGroupOperationWithMultipleFields() { GroupOperation operation = new GroupOperation(fields("a").and("b", "c")); Document groupClause = extractDocumentFromGroupOperation(operation); Document idClause = DocumentTestUtils.getAsDocument(groupClause, UNDERSCORE_ID); - assertThat(idClause.get("a")).isEqualTo((Object) "$a"); - assertThat(idClause.get("b")).isEqualTo((Object) "$c"); + assertThat(idClause).containsEntry("a", "$a") + .containsEntry("b", "$c"); } @Test - public void groupFactoryMethodWithMultipleFieldsAndSumOperation() { + void groupFactoryMethodWithMultipleFieldsAndSumOperation() { GroupOperation groupOperation = Aggregation.group(fields("a", "b").and("c")) // .sum("e").as("e"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document eOp = DocumentTestUtils.getAsDocument(groupClause, "e"); - assertThat(eOp).isEqualTo((Document) new Document("$sum", "$e")); + assertThat(eOp).isEqualTo(new Document("$sum", "$e")); } @Test - public void groupFactoryMethodWithMultipleFieldsAndSumOperationWithAlias() { + void groupFactoryMethodWithMultipleFieldsAndSumOperationWithAlias() { GroupOperation groupOperation = Aggregation.group(fields("a", "b").and("c")) // .sum("e").as("ee"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document eOp = DocumentTestUtils.getAsDocument(groupClause, "ee"); - assertThat(eOp).isEqualTo((Document) new Document("$sum", "$e")); + assertThat(eOp).isEqualTo(new Document("$sum", "$e")); } @Test - public void groupFactoryMethodWithMultipleFieldsAndCountOperationWithout() { + void groupFactoryMethodWithMultipleFieldsAndCountOperationWithout() { GroupOperation groupOperation = Aggregation.group(fields("a", "b").and("c")) // .count().as("count"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document eOp = DocumentTestUtils.getAsDocument(groupClause, "count"); - assertThat(eOp).isEqualTo((Document) new Document("$sum", 1)); + assertThat(eOp).isEqualTo(new Document("$sum", 1)); } @Test - public void groupFactoryMethodWithMultipleFieldsAndMultipleAggregateOperationsWithAlias() { + void groupFactoryMethodWithMultipleFieldsAndMultipleAggregateOperationsWithAlias() { GroupOperation groupOperation = Aggregation.group(fields("a", "b").and("c")) // .sum("e").as("sum") // @@ -130,58 +131,58 @@ public void groupFactoryMethodWithMultipleFieldsAndMultipleAggregateOperationsWi Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document sum = DocumentTestUtils.getAsDocument(groupClause, "sum"); - assertThat(sum).isEqualTo((Document) new Document("$sum", "$e")); + assertThat(sum).isEqualTo(new Document("$sum", "$e")); Document min = DocumentTestUtils.getAsDocument(groupClause, "min"); - assertThat(min).isEqualTo((Document) new Document("$min", "$e")); + assertThat(min).isEqualTo(new Document("$min", "$e")); } @Test - public void groupOperationPushWithValue() { + void groupOperationPushWithValue() { GroupOperation groupOperation = Aggregation.group("a", "b").push(1).as("x"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document push = DocumentTestUtils.getAsDocument(groupClause, "x"); - assertThat(push).isEqualTo((Document) new Document("$push", 1)); + assertThat(push).isEqualTo(new Document("$push", 1)); } @Test - public void groupOperationPushWithReference() { + void groupOperationPushWithReference() { GroupOperation groupOperation = Aggregation.group("a", "b").push("ref").as("x"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document push = DocumentTestUtils.getAsDocument(groupClause, "x"); - assertThat(push).isEqualTo((Document) new Document("$push", "$ref")); + assertThat(push).isEqualTo(new Document("$push", "$ref")); } @Test - public void groupOperationAddToSetWithReference() { + void groupOperationAddToSetWithReference() { GroupOperation groupOperation = Aggregation.group("a", "b").addToSet("ref").as("x"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document push = DocumentTestUtils.getAsDocument(groupClause, "x"); - assertThat(push).isEqualTo((Document) new Document("$addToSet", "$ref")); + assertThat(push).isEqualTo(new Document("$addToSet", "$ref")); } @Test - public void groupOperationAddToSetWithValue() { + void groupOperationAddToSetWithValue() { GroupOperation groupOperation = Aggregation.group("a", "b").addToSet(42).as("x"); Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document push = DocumentTestUtils.getAsDocument(groupClause, "x"); - assertThat(push).isEqualTo((Document) new Document("$addToSet", 42)); + assertThat(push).isEqualTo(new Document("$addToSet", 42)); } @Test // DATAMONGO-979 - public void shouldRenderSizeExpressionInGroup() { + void shouldRenderSizeExpressionInGroup() { GroupOperation groupOperation = Aggregation // .group("username") // @@ -191,11 +192,13 @@ public void shouldRenderSizeExpressionInGroup() { Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document tagsCount = DocumentTestUtils.getAsDocument(groupClause, "tags_count"); - assertThat(tagsCount.get("$first")).isEqualTo((Object) new Document("$size", Arrays.asList("$tags"))); + assertThat(tagsCount) + .containsEntry("$first", new Document("$size", Collections + .singletonList("$tags"))); } @Test // DATAMONGO-1327 - public void groupOperationStdDevSampWithValue() { + void groupOperationStdDevSampWithValue() { GroupOperation groupOperation = Aggregation.group("a", "b").stdDevSamp("field").as("fieldStdDevSamp"); @@ -206,7 +209,7 @@ public void groupOperationStdDevSampWithValue() { } @Test // DATAMONGO-1327 - public void groupOperationStdDevPopWithValue() { + void groupOperationStdDevPopWithValue() { GroupOperation groupOperation = Aggregation.group("a", "b").stdDevPop("field").as("fieldStdDevPop"); @@ -217,7 +220,7 @@ public void groupOperationStdDevPopWithValue() { } @Test // DATAMONGO-1784 - public void shouldRenderSumWithExpressionInGroup() { + void shouldRenderSumWithExpressionInGroup() { GroupOperation groupOperation = Aggregation // .group("username") // @@ -230,12 +233,12 @@ public void shouldRenderSumWithExpressionInGroup() { Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document foobar = DocumentTestUtils.getAsDocument(groupClause, "foobar"); - assertThat(foobar.get("$sum")).isEqualTo(new Document("$cond", + assertThat(foobar).containsEntry("$sum", new Document("$cond", new Document("if", new Document("$eq", Arrays.asList("$foo", "bar"))).append("then", 1).append("else", -1))); } @Test // DATAMONGO-1784 - public void sumWithNullExpressionShouldThrowException() { + void sumWithNullExpressionShouldThrowException() { assertThatIllegalArgumentException() .isThrownBy(() -> Aggregation.group("username").sum((AggregationExpression) null)); } @@ -251,7 +254,7 @@ void accumulatorShouldBeAllowedOnGroupOperation() { Document groupClause = extractDocumentFromGroupOperation(groupOperation); Document accumulatedValue = DocumentTestUtils.getAsDocument(groupClause, "accumulated-value"); - assertThat(accumulatedValue.get("$accumulator")).isNotNull(); + assertThat(accumulatedValue).containsKey("$accumulator"); } private Document extractDocumentFromGroupOperation(GroupOperation groupOperation) { From ad6d2c97b7b03e14fe3233509fd13588fc33db92 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 12 Jan 2021 11:49:19 +0100 Subject: [PATCH 0313/1381] Update copyright year to 2021. Closes #3534 --- .../mongodb/core/ProjectionsBenchmark.java | 2 +- .../core/convert/DbRefMappingBenchmark.java | 2 +- .../MappingMongoConverterBenchmark.java | 2 +- .../AbstractMicrobenchmark.java | 2 +- .../microbenchmark/HttpResultsWriter.java | 2 +- .../microbenchmark/MongoResultsWriter.java | 2 +- .../mongodb/microbenchmark/ResultsWriter.java | 2 +- .../data/mongodb/BulkOperationException.java | 2 +- .../data/mongodb/ClientSessionException.java | 2 +- .../data/mongodb/CodecRegistryProvider.java | 2 +- .../InvalidMongoDbApiUsageException.java | 2 +- .../data/mongodb/LazyLoadingException.java | 2 +- .../data/mongodb/MongoCollectionUtils.java | 2 +- .../data/mongodb/MongoDatabaseFactory.java | 2 +- .../data/mongodb/MongoDatabaseUtils.java | 2 +- .../data/mongodb/MongoDbFactory.java | 2 +- .../data/mongodb/MongoResourceHolder.java | 2 +- .../data/mongodb/MongoSessionProvider.java | 2 +- .../mongodb/MongoTransactionException.java | 2 +- .../data/mongodb/MongoTransactionManager.java | 2 +- .../mongodb/ReactiveMongoDatabaseFactory.java | 2 +- .../mongodb/ReactiveMongoDatabaseUtils.java | 2 +- .../mongodb/ReactiveMongoResourceHolder.java | 2 +- .../ReactiveMongoTransactionManager.java | 24 +++++++++---------- .../SessionAwareMethodInterceptor.java | 2 +- .../data/mongodb/SessionSynchronization.java | 2 +- .../data/mongodb/SpringDataMongoDB.java | 2 +- .../UncategorizedMongoDbException.java | 2 +- .../AbstractMongoClientConfiguration.java | 2 +- .../AbstractReactiveMongoConfiguration.java | 2 +- .../data/mongodb/config/BeanNames.java | 2 +- .../ConnectionStringPropertyEditor.java | 2 +- .../mongodb/config/EnableMongoAuditing.java | 2 +- .../config/EnableReactiveMongoAuditing.java | 2 +- .../mongodb/config/GeoJsonConfiguration.java | 2 +- .../mongodb/config/GridFsTemplateParser.java | 2 +- .../config/MappingMongoConverterParser.java | 2 +- .../MongoAuditingBeanDefinitionParser.java | 2 +- .../config/MongoAuditingRegistrar.java | 2 +- .../mongodb/config/MongoClientParser.java | 2 +- .../config/MongoConfigurationSupport.java | 2 +- .../config/MongoCredentialPropertyEditor.java | 2 +- .../mongodb/config/MongoDbFactoryParser.java | 2 +- .../data/mongodb/config/MongoJmxParser.java | 2 +- .../mongodb/config/MongoNamespaceHandler.java | 2 +- .../mongodb/config/MongoParsingUtils.java | 4 ++-- .../mongodb/config/MongoTemplateParser.java | 2 +- .../config/PersistentEntitiesFactoryBean.java | 2 +- .../ReactiveMongoAuditingRegistrar.java | 2 +- .../config/ReadConcernPropertyEditor.java | 2 +- .../config/ReadPreferencePropertyEditor.java | 2 +- .../config/ServerAddressPropertyEditor.java | 2 +- .../config/StringToWriteConcernConverter.java | 2 +- .../UUidRepresentationPropertyEditor.java | 2 +- .../config/WriteConcernPropertyEditor.java | 2 +- .../data/mongodb/core/AggregationUtil.java | 2 +- .../data/mongodb/core/BulkOperations.java | 2 +- .../data/mongodb/core/ChangeStreamEvent.java | 2 +- .../mongodb/core/ChangeStreamOptions.java | 2 +- .../data/mongodb/core/CollectionCallback.java | 2 +- .../data/mongodb/core/CollectionOptions.java | 2 +- .../data/mongodb/core/CountQuery.java | 2 +- .../data/mongodb/core/CursorPreparer.java | 2 +- .../data/mongodb/core/DbCallback.java | 2 +- .../mongodb/core/DefaultBulkOperations.java | 2 +- .../mongodb/core/DefaultIndexOperations.java | 2 +- .../core/DefaultIndexOperationsProvider.java | 2 +- .../core/DefaultReactiveIndexOperations.java | 2 +- .../mongodb/core/DefaultScriptOperations.java | 2 +- .../core/DefaultWriteConcernResolver.java | 2 +- .../mongodb/core/DocumentCallbackHandler.java | 2 +- .../data/mongodb/core/EntityOperations.java | 2 +- .../core/ExecutableAggregationOperation.java | 2 +- ...ExecutableAggregationOperationSupport.java | 2 +- .../mongodb/core/ExecutableFindOperation.java | 2 +- .../core/ExecutableFindOperationSupport.java | 2 +- .../core/ExecutableInsertOperation.java | 2 +- .../ExecutableInsertOperationSupport.java | 2 +- .../core/ExecutableMapReduceOperation.java | 2 +- .../ExecutableMapReduceOperationSupport.java | 4 ++-- .../core/ExecutableRemoveOperation.java | 2 +- .../ExecutableRemoveOperationSupport.java | 2 +- .../core/ExecutableUpdateOperation.java | 2 +- .../ExecutableUpdateOperationSupport.java | 2 +- .../mongodb/core/FindAndModifyOptions.java | 2 +- .../mongodb/core/FindAndReplaceOptions.java | 2 +- .../mongodb/core/FindPublisherPreparer.java | 2 +- .../mongodb/core/FluentMongoOperations.java | 2 +- .../mongodb/core/GeoCommandStatistics.java | 2 +- .../data/mongodb/core/IndexConverters.java | 2 +- .../data/mongodb/core/MappedDocument.java | 2 +- .../core/MappingMongoJsonSchemaCreator.java | 2 +- .../data/mongodb/core/MongoAction.java | 2 +- .../mongodb/core/MongoActionOperation.java | 2 +- .../data/mongodb/core/MongoAdmin.java | 2 +- .../mongodb/core/MongoAdminOperations.java | 2 +- .../mongodb/core/MongoClientFactoryBean.java | 2 +- .../core/MongoClientSettingsFactoryBean.java | 2 +- .../MongoDataIntegrityViolationException.java | 2 +- .../core/MongoDatabaseFactorySupport.java | 2 +- .../mongodb/core/MongoDbFactorySupport.java | 2 +- .../MongoEncryptionSettingsFactoryBean.java | 2 +- .../core/MongoExceptionTranslator.java | 2 +- .../mongodb/core/MongoJsonSchemaCreator.java | 2 +- .../data/mongodb/core/MongoOperations.java | 2 +- .../data/mongodb/core/MongoTemplate.java | 2 +- .../data/mongodb/core/PropertyOperations.java | 2 +- .../data/mongodb/core/QueryOperations.java | 2 +- .../core/ReactiveAggregationOperation.java | 2 +- .../ReactiveAggregationOperationSupport.java | 2 +- .../core/ReactiveChangeStreamOperation.java | 2 +- .../ReactiveChangeStreamOperationSupport.java | 2 +- .../core/ReactiveCollectionCallback.java | 2 +- .../core/ReactiveDatabaseCallback.java | 2 +- .../mongodb/core/ReactiveFindOperation.java | 2 +- .../core/ReactiveFindOperationSupport.java | 2 +- .../core/ReactiveFluentMongoOperations.java | 2 +- .../mongodb/core/ReactiveInsertOperation.java | 2 +- .../core/ReactiveInsertOperationSupport.java | 2 +- .../core/ReactiveMapReduceOperation.java | 2 +- .../ReactiveMapReduceOperationSupport.java | 2 +- .../core/ReactiveMongoClientFactoryBean.java | 2 +- ...eactiveMongoClientSettingsFactoryBean.java | 2 +- .../mongodb/core/ReactiveMongoContext.java | 2 +- .../mongodb/core/ReactiveMongoOperations.java | 2 +- .../mongodb/core/ReactiveMongoTemplate.java | 2 +- .../mongodb/core/ReactiveRemoveOperation.java | 2 +- .../core/ReactiveRemoveOperationSupport.java | 2 +- .../mongodb/core/ReactiveSessionCallback.java | 2 +- .../mongodb/core/ReactiveSessionScoped.java | 2 +- .../mongodb/core/ReactiveUpdateOperation.java | 2 +- .../core/ReactiveUpdateOperationSupport.java | 2 +- .../mongodb/core/ReadPreferenceAware.java | 2 +- .../data/mongodb/core/ScriptOperations.java | 2 +- .../data/mongodb/core/SessionCallback.java | 2 +- .../data/mongodb/core/SessionScoped.java | 2 +- .../SimpleMongoClientDatabaseFactory.java | 2 +- .../core/SimpleMongoClientDbFactory.java | 2 +- .../SimpleReactiveMongoDatabaseFactory.java | 2 +- .../mongodb/core/WriteConcernResolver.java | 2 +- .../mongodb/core/WriteResultChecking.java | 2 +- .../core/aggregation/AddFieldsOperation.java | 4 ++-- .../mongodb/core/aggregation/Aggregation.java | 2 +- .../aggregation/AggregationExpression.java | 2 +- .../AggregationExpressionTransformer.java | 2 +- .../AggregationFunctionExpressions.java | 2 +- .../aggregation/AggregationOperation.java | 2 +- .../AggregationOperationContext.java | 4 ++-- .../AggregationOperationRenderer.java | 2 +- .../core/aggregation/AggregationOptions.java | 2 +- .../core/aggregation/AggregationPipeline.java | 2 +- .../core/aggregation/AggregationResults.java | 2 +- .../AggregationSpELExpression.java | 2 +- .../core/aggregation/AggregationUpdate.java | 2 +- .../core/aggregation/AggregationUtils.java | 2 +- .../core/aggregation/ArrayOperators.java | 2 +- .../core/aggregation/BucketAutoOperation.java | 4 ++-- .../core/aggregation/BucketOperation.java | 4 ++-- .../aggregation/BucketOperationSupport.java | 2 +- .../core/aggregation/ComparisonOperators.java | 2 +- .../aggregation/ConditionalOperators.java | 2 +- .../core/aggregation/ConvertOperators.java | 2 +- .../core/aggregation/CountOperation.java | 2 +- .../DocumentEnhancingOperation.java | 4 ++-- .../core/aggregation/ExposedFields.java | 2 +- ...osedFieldsAggregationOperationContext.java | 2 +- .../core/aggregation/FacetOperation.java | 4 ++-- .../data/mongodb/core/aggregation/Field.java | 2 +- .../data/mongodb/core/aggregation/Fields.java | 2 +- .../FieldsExposingAggregationOperation.java | 2 +- .../core/aggregation/GeoNearOperation.java | 2 +- .../aggregation/GraphLookupOperation.java | 2 +- ...osedFieldsAggregationOperationContext.java | 2 +- .../core/aggregation/LimitOperation.java | 4 ++-- .../core/aggregation/LookupOperation.java | 4 ++-- .../core/aggregation/MatchOperation.java | 4 ++-- .../core/aggregation/MergeOperation.java | 4 ++-- .../core/aggregation/ObjectOperators.java | 4 ++-- .../core/aggregation/OutOperation.java | 4 ++-- ...DelegatingAggregationOperationContext.java | 2 +- .../core/aggregation/ProjectionOperation.java | 2 +- .../core/aggregation/RedactOperation.java | 4 ++-- ...dTypeBasedAggregationOperationContext.java | 2 +- .../aggregation/ReplaceRootOperation.java | 4 ++-- .../aggregation/ReplaceWithOperation.java | 2 +- .../core/aggregation/SampleOperation.java | 4 ++-- .../core/aggregation/ScriptOperators.java | 2 +- .../core/aggregation/SetOperation.java | 4 ++-- .../core/aggregation/SkipOperation.java | 4 ++-- .../aggregation/SortByCountOperation.java | 4 ++-- .../core/aggregation/SortOperation.java | 4 ++-- .../SpelExpressionTransformer.java | 2 +- .../core/aggregation/StringOperators.java | 4 ++-- .../TypeBasedAggregationOperationContext.java | 2 +- .../core/aggregation/TypedAggregation.java | 2 +- .../core/aggregation/UnionWithOperation.java | 2 +- .../core/aggregation/UnsetOperation.java | 4 ++-- .../core/aggregation/UnwindOperation.java | 2 +- .../core/convert/AbstractMongoConverter.java | 2 +- .../core/convert/CustomConversions.java | 2 +- .../core/convert/DbRefProxyHandler.java | 2 +- .../mongodb/core/convert/DbRefResolver.java | 2 +- .../core/convert/DbRefResolverCallback.java | 2 +- .../convert/DefaultDbRefProxyHandler.java | 2 +- .../core/convert/DefaultDbRefResolver.java | 2 +- .../convert/DefaultDbRefResolverCallback.java | 2 +- .../core/convert/DefaultMongoTypeMapper.java | 2 +- .../core/convert/DocumentAccessor.java | 2 +- .../convert/DocumentPropertyAccessor.java | 2 +- .../mongodb/core/convert/GeoConverters.java | 2 +- .../core/convert/JsonSchemaMapper.java | 2 +- .../core/convert/LazyLoadingProxy.java | 2 +- .../core/convert/MappingMongoConverter.java | 2 +- .../mongodb/core/convert/MongoConverter.java | 2 +- .../mongodb/core/convert/MongoConverters.java | 2 +- .../core/convert/MongoCustomConversions.java | 2 +- .../core/convert/MongoExampleMapper.java | 2 +- .../core/convert/MongoJsonSchemaMapper.java | 2 +- .../mongodb/core/convert/MongoTypeMapper.java | 2 +- .../mongodb/core/convert/MongoWriter.java | 2 +- .../core/convert/NoOpDbRefResolver.java | 2 +- .../data/mongodb/core/convert/ObjectPath.java | 2 +- .../mongodb/core/convert/QueryMapper.java | 2 +- .../mongodb/core/convert/UpdateMapper.java | 2 +- .../mongodb/core/convert/ValueResolver.java | 2 +- .../data/mongodb/core/geo/GeoJson.java | 2 +- .../core/geo/GeoJsonGeometryCollection.java | 2 +- .../mongodb/core/geo/GeoJsonLineString.java | 2 +- .../data/mongodb/core/geo/GeoJsonModule.java | 2 +- .../core/geo/GeoJsonMultiLineString.java | 2 +- .../mongodb/core/geo/GeoJsonMultiPoint.java | 2 +- .../mongodb/core/geo/GeoJsonMultiPolygon.java | 2 +- .../data/mongodb/core/geo/GeoJsonPoint.java | 2 +- .../data/mongodb/core/geo/GeoJsonPolygon.java | 2 +- .../data/mongodb/core/geo/Sphere.java | 2 +- .../mongodb/core/index/CompoundIndex.java | 2 +- .../core/index/CompoundIndexDefinition.java | 2 +- .../mongodb/core/index/CompoundIndexes.java | 2 +- .../mongodb/core/index/DurationStyle.java | 2 +- .../core/index/GeoSpatialIndexType.java | 2 +- .../mongodb/core/index/GeoSpatialIndexed.java | 2 +- .../mongodb/core/index/GeospatialIndex.java | 2 +- .../data/mongodb/core/index/HashIndexed.java | 2 +- .../data/mongodb/core/index/HashedIndex.java | 2 +- .../data/mongodb/core/index/Index.java | 2 +- .../mongodb/core/index/IndexDefinition.java | 2 +- .../mongodb/core/index/IndexDirection.java | 2 +- .../data/mongodb/core/index/IndexField.java | 2 +- .../data/mongodb/core/index/IndexFilter.java | 2 +- .../data/mongodb/core/index/IndexInfo.java | 2 +- .../mongodb/core/index/IndexOperations.java | 2 +- .../core/index/IndexOperationsAdapter.java | 2 +- .../core/index/IndexOperationsProvider.java | 2 +- .../mongodb/core/index/IndexPredicate.java | 2 +- .../mongodb/core/index/IndexResolver.java | 2 +- .../data/mongodb/core/index/Indexed.java | 6 ++--- .../index/MongoMappingEventPublisher.java | 2 +- .../MongoPersistentEntityIndexCreator.java | 2 +- .../MongoPersistentEntityIndexResolver.java | 2 +- .../core/index/ReactiveIndexOperations.java | 2 +- .../ReactiveIndexOperationsProvider.java | 2 +- ...tiveMongoPersistentEntityIndexCreator.java | 2 +- .../core/index/TextIndexDefinition.java | 2 +- .../data/mongodb/core/index/TextIndexed.java | 2 +- .../mapping/BasicMongoPersistentEntity.java | 2 +- .../mapping/BasicMongoPersistentProperty.java | 2 +- .../CachingMongoPersistentProperty.java | 4 ++-- .../data/mongodb/core/mapping/DBRef.java | 2 +- .../data/mongodb/core/mapping/Document.java | 2 +- .../data/mongodb/core/mapping/Field.java | 2 +- .../data/mongodb/core/mapping/FieldType.java | 2 +- .../data/mongodb/core/mapping/Language.java | 2 +- .../data/mongodb/core/mapping/MongoId.java | 2 +- .../core/mapping/MongoMappingContext.java | 2 +- .../core/mapping/MongoPersistentEntity.java | 2 +- .../core/mapping/MongoPersistentProperty.java | 2 +- .../core/mapping/MongoSimpleTypes.java | 2 +- .../data/mongodb/core/mapping/ShardKey.java | 2 +- .../data/mongodb/core/mapping/Sharded.java | 2 +- .../core/mapping/ShardingStrategy.java | 2 +- .../data/mongodb/core/mapping/TextScore.java | 2 +- .../mapping/event/AbstractDeleteEvent.java | 2 +- .../event/AbstractMongoEventListener.java | 2 +- .../mapping/event/AfterConvertCallback.java | 2 +- .../core/mapping/event/AfterConvertEvent.java | 2 +- .../core/mapping/event/AfterDeleteEvent.java | 2 +- .../core/mapping/event/AfterLoadEvent.java | 2 +- .../core/mapping/event/AfterSaveCallback.java | 2 +- .../core/mapping/event/AfterSaveEvent.java | 2 +- .../mapping/event/AuditingEntityCallback.java | 4 ++-- .../mapping/event/AuditingEventListener.java | 2 +- .../mapping/event/BeforeConvertCallback.java | 2 +- .../mapping/event/BeforeConvertEvent.java | 2 +- .../core/mapping/event/BeforeDeleteEvent.java | 2 +- .../mapping/event/BeforeSaveCallback.java | 2 +- .../core/mapping/event/BeforeSaveEvent.java | 2 +- .../mapping/event/LoggingEventListener.java | 2 +- .../core/mapping/event/MongoMappingEvent.java | 2 +- .../event/ReactiveAfterConvertCallback.java | 2 +- .../event/ReactiveAfterSaveCallback.java | 2 +- .../event/ReactiveAuditingEntityCallback.java | 2 +- .../event/ReactiveBeforeConvertCallback.java | 2 +- .../event/ReactiveBeforeSaveCallback.java | 2 +- .../event/ValidatingMongoEventListener.java | 2 +- .../data/mongodb/core/mapreduce/GroupBy.java | 2 +- .../core/mapreduce/GroupByResults.java | 2 +- .../core/mapreduce/MapReduceCounts.java | 2 +- .../core/mapreduce/MapReduceOptions.java | 2 +- .../core/mapreduce/MapReduceResults.java | 2 +- .../core/mapreduce/MapReduceTiming.java | 2 +- .../mongodb/core/messaging/Cancelable.java | 2 +- .../core/messaging/ChangeStreamRequest.java | 2 +- .../core/messaging/ChangeStreamTask.java | 2 +- .../core/messaging/CursorReadingTask.java | 2 +- .../DefaultMessageListenerContainer.java | 2 +- .../LazyMappingDelegatingMessage.java | 8 +++---- .../data/mongodb/core/messaging/Message.java | 2 +- .../core/messaging/MessageListener.java | 2 +- .../messaging/MessageListenerContainer.java | 2 +- .../mongodb/core/messaging/SimpleMessage.java | 2 +- .../mongodb/core/messaging/Subscription.java | 2 +- .../core/messaging/SubscriptionRequest.java | 2 +- .../core/messaging/TailableCursorRequest.java | 2 +- .../core/messaging/TailableCursorTask.java | 4 ++-- .../data/mongodb/core/messaging/Task.java | 2 +- .../mongodb/core/messaging/TaskFactory.java | 2 +- .../data/mongodb/core/query/BasicQuery.java | 2 +- .../data/mongodb/core/query/BasicUpdate.java | 2 +- .../data/mongodb/core/query/Collation.java | 2 +- .../data/mongodb/core/query/Criteria.java | 2 +- .../core/query/CriteriaDefinition.java | 2 +- .../data/mongodb/core/query/Field.java | 2 +- .../data/mongodb/core/query/GeoCommand.java | 2 +- .../data/mongodb/core/query/Meta.java | 2 +- .../mongodb/core/query/MetricConversion.java | 2 +- .../mongodb/core/query/MongoRegexCreator.java | 2 +- .../data/mongodb/core/query/NearQuery.java | 2 +- .../data/mongodb/core/query/Query.java | 2 +- .../core/query/SerializationUtils.java | 2 +- .../data/mongodb/core/query/Term.java | 8 +++---- .../data/mongodb/core/query/TextCriteria.java | 6 ++--- .../data/mongodb/core/query/TextQuery.java | 2 +- .../core/query/UntypedExampleMatcher.java | 2 +- .../data/mongodb/core/query/Update.java | 2 +- .../mongodb/core/query/UpdateDefinition.java | 2 +- .../core/schema/DefaultMongoJsonSchema.java | 4 ++-- .../core/schema/DocumentJsonSchema.java | 4 ++-- .../IdentifiableJsonSchemaProperty.java | 2 +- .../mongodb/core/schema/JsonSchemaObject.java | 6 ++--- .../core/schema/JsonSchemaProperty.java | 2 +- .../mongodb/core/schema/MongoJsonSchema.java | 2 +- .../core/schema/TypedJsonSchemaObject.java | 2 +- .../core/schema/UntypedJsonSchemaObject.java | 2 +- .../core/script/ExecutableMongoScript.java | 2 +- .../mongodb/core/script/NamedMongoScript.java | 2 +- .../mongodb/core/spel/ExpressionNode.java | 2 +- ...xpressionTransformationContextSupport.java | 2 +- .../core/spel/ExpressionTransformer.java | 2 +- .../data/mongodb/core/spel/LiteralNode.java | 2 +- .../core/spel/MethodReferenceNode.java | 2 +- .../data/mongodb/core/spel/OperatorNode.java | 2 +- .../core/validation/CriteriaValidator.java | 2 +- .../core/validation/DocumentValidator.java | 2 +- .../core/validation/JsonSchemaValidator.java | 2 +- .../mongodb/core/validation/Validator.java | 2 +- .../data/mongodb/gridfs/AntPath.java | 2 +- .../data/mongodb/gridfs/GridFsCriteria.java | 2 +- .../data/mongodb/gridfs/GridFsObject.java | 2 +- .../data/mongodb/gridfs/GridFsOperations.java | 2 +- .../gridfs/GridFsOperationsSupport.java | 2 +- .../data/mongodb/gridfs/GridFsResource.java | 2 +- .../data/mongodb/gridfs/GridFsTemplate.java | 2 +- .../data/mongodb/gridfs/GridFsUpload.java | 2 +- .../gridfs/ReactiveGridFsOperations.java | 2 +- .../gridfs/ReactiveGridFsResource.java | 2 +- .../gridfs/ReactiveGridFsTemplate.java | 2 +- .../mongodb/gridfs/ReactiveGridFsUpload.java | 2 +- .../data/mongodb/monitor/AbstractMonitor.java | 2 +- .../data/mongodb/monitor/AssertMetrics.java | 2 +- .../monitor/BackgroundFlushingMetrics.java | 2 +- .../mongodb/monitor/BtreeIndexCounters.java | 2 +- .../mongodb/monitor/ConnectionMetrics.java | 2 +- .../mongodb/monitor/GlobalLockMetrics.java | 2 +- .../data/mongodb/monitor/MemoryMetrics.java | 2 +- .../mongodb/monitor/OperationCounters.java | 2 +- .../data/mongodb/monitor/ServerInfo.java | 2 +- .../data/mongodb/repository/Aggregation.java | 2 +- .../data/mongodb/repository/CountQuery.java | 2 +- .../data/mongodb/repository/DeleteQuery.java | 2 +- .../data/mongodb/repository/ExistsQuery.java | 2 +- .../data/mongodb/repository/Meta.java | 2 +- .../mongodb/repository/MongoRepository.java | 2 +- .../data/mongodb/repository/Near.java | 2 +- .../data/mongodb/repository/Query.java | 2 +- .../repository/ReactiveMongoRepository.java | 2 +- .../data/mongodb/repository/Tailable.java | 2 +- .../repository/cdi/MongoRepositoryBean.java | 2 +- .../cdi/MongoRepositoryExtension.java | 2 +- .../config/EnableMongoRepositories.java | 4 ++-- .../EnableReactiveMongoRepositories.java | 4 ++-- .../config/MongoRepositoriesRegistrar.java | 2 +- ...MongoRepositoryConfigNamespaceHandler.java | 2 +- ...MongoRepositoryConfigurationExtension.java | 2 +- .../ReactiveMongoRepositoriesRegistrar.java | 2 +- ...MongoRepositoryConfigurationExtension.java | 2 +- .../repository/query/AbstractMongoQuery.java | 2 +- .../query/AbstractReactiveMongoQuery.java | 2 +- .../repository/query/AggregationUtils.java | 2 +- .../mongodb/repository/query/BooleanUtil.java | 2 +- .../repository/query/CollationUtils.java | 2 +- .../query/ConvertingParameterAccessor.java | 2 +- .../query/DefaultSpELExpressionEvaluator.java | 2 +- .../query/DtoInstantiatingConverter.java | 2 +- .../query/MongoEntityInformation.java | 4 ++-- .../repository/query/MongoEntityMetadata.java | 4 ++-- .../query/MongoParameterAccessor.java | 2 +- .../repository/query/MongoParameters.java | 2 +- .../MongoParametersParameterAccessor.java | 2 +- .../repository/query/MongoQueryCreator.java | 2 +- .../repository/query/MongoQueryExecution.java | 2 +- .../repository/query/MongoQueryMethod.java | 2 +- .../repository/query/PartTreeMongoQuery.java | 2 +- .../mongodb/repository/query/QueryUtils.java | 2 +- .../query/ReactiveMongoParameterAccessor.java | 2 +- .../query/ReactiveMongoQueryExecution.java | 2 +- .../query/ReactiveMongoQueryMethod.java | 2 +- .../query/ReactivePartTreeMongoQuery.java | 2 +- .../query/ReactiveStringBasedAggregation.java | 2 +- .../query/ReactiveStringBasedMongoQuery.java | 2 +- .../query/SimpleMongoEntityMetadata.java | 2 +- .../query/StringBasedAggregation.java | 2 +- .../query/StringBasedMongoQuery.java | 2 +- .../support/CachingExpressionParser.java | 2 +- .../IndexEnsuringQueryCreationListener.java | 2 +- .../MappingMongoEntityInformation.java | 2 +- .../support/MongoAnnotationProcessor.java | 2 +- .../MongoEntityInformationSupport.java | 2 +- .../support/MongoRepositoryFactory.java | 2 +- .../support/MongoRepositoryFactoryBean.java | 2 +- .../support/MongodbDocumentSerializer.java | 2 +- .../support/QuerydslAbstractMongodbQuery.java | 2 +- .../support/QuerydslAnyEmbeddedBuilder.java | 4 ++-- .../QuerydslFetchableMongodbQuery.java | 2 +- .../support/QuerydslJoinBuilder.java | 2 +- .../repository/support/QuerydslMongoOps.java | 2 +- .../QuerydslMongoPredicateExecutor.java | 2 +- .../support/QuerydslMongoRepository.java | 2 +- .../QuerydslPredicateExecutorSupport.java | 2 +- .../support/QuerydslRepositorySupport.java | 2 +- .../ReactiveMongoRepositoryFactory.java | 2 +- .../ReactiveMongoRepositoryFactoryBean.java | 2 +- ...eactiveQuerydslMongoPredicateExecutor.java | 16 ++++++------- .../ReactiveSpringDataMongodbQuery.java | 2 +- .../support/SimpleMongoRepository.java | 2 +- .../SimpleReactiveMongoRepository.java | 2 +- .../support/SpringDataMongodbQuery.java | 2 +- .../support/SpringDataMongodbSerializer.java | 2 +- .../data/mongodb/util/BsonUtils.java | 2 +- .../data/mongodb/util/DBObjectUtils.java | 2 +- .../data/mongodb/util/MongoClientVersion.java | 2 +- .../data/mongodb/util/MongoDbErrorCodes.java | 2 +- .../mongodb/util/json/DateTimeFormatter.java | 2 +- .../data/mongodb/util/json/JsonBuffer.java | 2 +- .../data/mongodb/util/json/JsonScanner.java | 2 +- .../data/mongodb/util/json/JsonToken.java | 2 +- .../data/mongodb/util/json/JsonTokenType.java | 2 +- .../util/json/ParameterBindingContext.java | 2 +- .../json/ParameterBindingDocumentCodec.java | 2 +- .../util/json/ParameterBindingJsonReader.java | 2 +- .../data/mongodb/util/json/ValueProvider.java | 2 +- ...xecutableAggregationOperationExtensions.kt | 2 +- .../core/ExecutableFindOperationExtensions.kt | 2 +- .../ExecutableInsertOperationExtensions.kt | 2 +- .../ExecutableMapReduceOperationExtensions.kt | 2 +- .../ExecutableRemoveOperationExtensions.kt | 2 +- .../ExecutableUpdateOperationExtensions.kt | 2 +- .../mongodb/core/MongoOperationsExtensions.kt | 2 +- .../ReactiveAggregationOperationExtensions.kt | 2 +- ...ReactiveChangeStreamOperationExtensions.kt | 2 +- .../core/ReactiveFindOperationExtensions.kt | 2 +- .../core/ReactiveInsertOperationExtensions.kt | 2 +- .../ReactiveMapReduceOperationExtensions.kt | 2 +- .../core/ReactiveMongoOperationsExtensions.kt | 2 +- .../core/ReactiveRemoveOperationExtensions.kt | 2 +- .../core/ReactiveUpdateOperationExtensions.kt | 2 +- .../mongodb/core/query/CriteriaExtensions.kt | 2 +- .../data/mongodb/core/query/KPropertyPath.kt | 2 +- .../core/query/KPropertyPathExtensions.kt | 2 +- .../core/query/TypedCriteriaExtensions.kt | 2 +- .../data/mongodb/config/spring-mongo-2.2.xsd | 2 +- .../data/mongodb/config/spring-mongo-3.0.xsd | 2 +- .../java/ConfigClassInDefaultPackage.java | 2 +- .../ConfigClassInDefaultPackageUnitTests.java | 2 +- .../src/test/java/example/first/First.java | 2 +- .../src/test/java/example/second/Second.java | 2 +- .../data/mongodb/DependencyTests.java | 2 +- .../mongodb/MongoDatabaseUtilsUnitTests.java | 2 +- .../MongoTransactionManagerUnitTests.java | 2 +- .../ReactiveMongoDatabaseUtilsUnitTests.java | 2 +- ...ctiveMongoTransactionManagerUnitTests.java | 2 +- .../ReactiveTransactionIntegrationTests.java | 2 +- ...essionAwareMethodInterceptorUnitTests.java | 2 +- .../data/mongodb/SpringDataMongoDBTests.java | 2 +- .../config/AbstractIntegrationTests.java | 2 +- .../AbstractMongoConfigurationUnitTests.java | 2 +- ...iveMongoConfigurationIntegrationTests.java | 2 +- ...ctReactiveMongoConfigurationUnitTests.java | 2 +- .../config/AuditingIntegrationTests.java | 2 +- ...uditingViaJavaConfigRepositoriesTests.java | 2 +- .../mongodb/config/CustomMongoTypeMapper.java | 2 +- .../GeoJsonConfigurationIntegrationTests.java | 2 +- ...gMongoConverterParserIntegrationTests.java | 2 +- ...erterParserValidationIntegrationTests.java | 2 +- .../MongoAuditingRegistrarUnitTests.java | 2 +- .../config/MongoClientNamespaceTests.java | 2 +- .../MongoClientParserIntegrationTests.java | 2 +- ...ongoCredentialPropertyEditorUnitTests.java | 2 +- .../MongoDbFactoryNoDatabaseRunningTests.java | 2 +- .../MongoDbFactoryParserIntegrationTests.java | 2 +- .../config/MongoNamespaceReplicaSetTests.java | 2 +- .../mongodb/config/MongoNamespaceTests.java | 2 +- .../config/MongoParserIntegrationTests.java | 2 +- .../mongodb/config/ReactiveAuditingTests.java | 2 +- ...ReadPreferencePropertyEditorUnitTests.java | 2 +- .../ServerAddressPropertyEditorUnitTests.java | 2 +- ...tringToWriteConcernConverterUnitTests.java | 2 +- .../WriteConcernPropertyEditorUnitTests.java | 2 +- .../data/mongodb/core/AuditablePerson.java | 2 +- .../core/ChangeStreamOptionsUnitTests.java | 2 +- .../data/mongodb/core/ClientSessionTests.java | 2 +- ...oseableIterableCursorAdapterUnitTests.java | 2 +- .../data/mongodb/core/CollationUnitTests.java | 2 +- .../mongodb/core/CountQueryUnitTests.java | 2 +- ...DefaultBulkOperationsIntegrationTests.java | 2 +- .../core/DefaultBulkOperationsUnitTests.java | 2 +- ...efaultIndexOperationsIntegrationTests.java | 2 +- .../core/DefaultIndexOperationsUnitTests.java | 2 +- .../DefaultReactiveIndexOperationsTests.java | 2 +- ...faultReactiveIndexOperationsUnitTests.java | 2 +- .../core/DefaultScriptOperationsTests.java | 2 +- .../DefaultScriptOperationsUnitTests.java | 2 +- .../data/mongodb/core/DocumentTestUtils.java | 2 +- .../core/EntityOperationUnitTests.java | 2 +- ...eAggregationOperationSupportUnitTests.java | 2 +- .../ExecutableFindOperationSupportTests.java | 2 +- ...utableInsertOperationSupportUnitTests.java | 2 +- ...bleMapReduceOperationSupportUnitTests.java | 2 +- ...ExecutableRemoveOperationSupportTests.java | 2 +- ...ExecutableUpdateOperationSupportTests.java | 2 +- .../data/mongodb/core/Friend.java | 2 +- .../core/GeoCommandStatisticsUnitTests.java | 2 +- .../data/mongodb/core/JmxServer.java | 2 +- .../mongodb/core/JsonSchemaQueryTests.java | 2 +- ...appingMongoJsonSchemaCreatorUnitTests.java | 2 +- .../core/MongoAdminIntegrationTests.java | 2 +- .../core/MongoClientFactoryBeanUnitTests.java | 2 +- ...ntSettingsFactoryBeanIntegrationTests.java | 2 +- ...ngoClientSettingsFactoryBeanUnitTests.java | 2 +- ...ngoEncryptionSettingsFactoryBeanTests.java | 2 +- .../MongoExceptionTranslatorUnitTests.java | 2 +- .../core/MongoOperationsUnitTests.java | 2 +- .../core/MongoTemplateCollationTests.java | 2 +- .../mongodb/core/MongoTemplateDbRefTests.java | 2 +- .../core/MongoTemplateMappingTests.java | 2 +- .../data/mongodb/core/MongoTemplateTests.java | 2 +- .../core/MongoTemplateTransactionTests.java | 2 +- .../mongodb/core/MongoTemplateUnitTests.java | 2 +- .../core/MongoTemplateUpdateTests.java | 2 +- .../core/MongoTemplateValidationTests.java | 2 +- .../data/mongodb/core/NoExplicitIdTests.java | 2 +- .../data/mongodb/core/Person.java | 2 +- .../data/mongodb/core/PersonExample.java | 2 +- .../mongodb/core/PersonExampleAppConfig.java | 2 +- .../data/mongodb/core/PersonWithAList.java | 2 +- .../PersonWithIdPropertyOfPrimitiveInt.java | 2 +- .../PersonWithIdPropertyOfPrimitiveLong.java | 2 +- .../PersonWithIdPropertyOfTypeBigInteger.java | 2 +- .../PersonWithIdPropertyOfTypeInteger.java | 2 +- .../core/PersonWithIdPropertyOfTypeLong.java | 2 +- .../PersonWithIdPropertyOfTypeObjectId.java | 2 +- .../PersonWithIdPropertyOfTypeString.java | 2 +- .../core/PersonWithIdPropertyOfTypeUUID.java | 2 +- ...ersonWithVersionPropertyOfTypeInteger.java | 2 +- .../PersonWithVersionPropertyOfTypeLong.java | 2 +- .../PersonWith_idPropertyOfTypeObjectId.java | 2 +- .../PersonWith_idPropertyOfTypeString.java | 2 +- .../mongodb/core/PersonWriteConverter.java | 2 +- .../data/mongodb/core/Portfolio.java | 2 +- .../mongodb/core/QueryByExampleTests.java | 2 +- .../core/QueryCursorPreparerUnitTests.java | 2 +- ...eAggregationOperationSupportUnitTests.java | 2 +- ...tiveChangeStreamOperationSupportTests.java | 2 +- ...ChangeStreamOperationSupportUnitTests.java | 2 +- .../core/ReactiveClientSessionTests.java | 2 +- .../ReactiveFindOperationSupportTests.java | 2 +- ...activeInsertOperationSupportUnitTests.java | 2 +- ...iveMapReduceOperationSupportUnitTests.java | 2 +- .../ReactiveMongoTemplateCollationTests.java | 2 +- .../ReactiveMongoTemplateExecuteTests.java | 2 +- .../core/ReactiveMongoTemplateIndexTests.java | 2 +- .../core/ReactiveMongoTemplateTests.java | 2 +- ...ReactiveMongoTemplateTransactionTests.java | 2 +- .../core/ReactiveMongoTemplateUnitTests.java | 2 +- .../ReactiveMongoTemplateUpdateTests.java | 2 +- .../ReactiveRemoveOperationSupportTests.java | 2 +- ...iveSessionBoundMongoTemplateUnitTests.java | 2 +- .../ReactiveUpdateOperationSupportTests.java | 2 +- .../core/SerializationUtilsUnitTests.java | 2 +- .../core/SessionBoundMongoTemplateTests.java | 2 +- .../SessionBoundMongoTemplateUnitTests.java | 2 +- .../ShardedEntityWithDefaultShardKey.java | 2 +- ...EntityWithNonDefaultImmutableShardKey.java | 2 +- .../ShardedEntityWithNonDefaultShardKey.java | 2 +- ...VersionedEntityWithNonDefaultShardKey.java | 2 +- ...leMongoClientDatabaseFactoryUnitTests.java | 2 +- ...ReactiveMongoDatabaseFactoryUnitTests.java | 2 +- .../data/mongodb/core/TestEntities.java | 2 +- .../mongodb/core/TestMongoConfiguration.java | 2 +- .../data/mongodb/core/Trade.java | 2 +- .../core/UpdateOperationsUnitTests.java | 2 +- .../data/mongodb/core/User.java | 2 +- .../data/mongodb/core/Venue.java | 2 +- .../AddFieldsOperationUnitTests.java | 2 +- .../aggregation/AggregationOptionsTests.java | 2 +- .../core/aggregation/AggregationTests.java | 2 +- .../aggregation/AggregationUnitTests.java | 2 +- .../AggregationUpdateUnitTests.java | 2 +- .../ArithmeticOperatorsUnitTests.java | 2 +- .../aggregation/ArrayOperatorsUnitTests.java | 2 +- .../BucketAutoOperationUnitTests.java | 2 +- .../aggregation/BucketOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/City.java | 2 +- .../aggregation/CondExpressionUnitTests.java | 2 +- .../ConvertOperatorsUnitTests.java | 2 +- .../aggregation/CountOperationUnitTests.java | 2 +- .../data/mongodb/core/aggregation/Data.java | 2 +- .../mongodb/core/aggregation/DataItem.java | 2 +- .../aggregation/ExposedFieldsUnitTests.java | 2 +- .../aggregation/FacetOperationUnitTests.java | 2 +- .../core/aggregation/FieldsUnitTests.java | 2 +- .../GeoNearOperationUnitTests.java | 2 +- .../GraphLookupOperationUnitTests.java | 2 +- .../mongodb/core/aggregation/Invoice.java | 2 +- .../mongodb/core/aggregation/LikeStats.java | 2 +- .../mongodb/core/aggregation/LineItem.java | 2 +- .../aggregation/LookupOperationUnitTests.java | 2 +- .../aggregation/MergeOperationUnitTests.java | 2 +- .../mongodb/core/aggregation/MeterData.java | 2 +- .../aggregation/ObjectOperatorsUnitTests.java | 2 +- .../data/mongodb/core/aggregation/Order.java | 2 +- .../aggregation/OutOperationUnitTest.java | 2 +- .../mongodb/core/aggregation/Product.java | 2 +- .../ProjectionOperationUnitTests.java | 2 +- .../aggregation/ReactiveAggregationTests.java | 2 +- .../ReactiveAggregationUnitTests.java | 2 +- .../aggregation/RedactOperationUnitTests.java | 2 +- .../ReplaceRootOperationUnitTests.java | 2 +- .../ReplaceWithOperationUnitTests.java | 2 +- .../aggregation/SampleOperationUnitTests.java | 2 +- .../aggregation/ScriptOperatorsUnitTests.java | 2 +- .../aggregation/SetOperationUnitTests.java | 2 +- .../aggregation/SkipOperationUnitTests.java | 2 +- .../SortByCountOperationUnitTests.java | 2 +- .../aggregation/SortOperationUnitTests.java | 2 +- ...ExpressionTransformerIntegrationTests.java | 2 +- .../SpelExpressionTransformerUnitTests.java | 2 +- .../mongodb/core/aggregation/StateStats.java | 2 +- .../aggregation/StringOperatorsUnitTests.java | 2 +- ...dAggregationOperationContextUnitTests.java | 2 +- .../UnionWithOperationUnitTests.java | 2 +- .../aggregation/UnsetOperationUnitTests.java | 2 +- .../aggregation/UnwindOperationUnitTests.java | 2 +- .../core/aggregation/UserWithLikes.java | 2 +- .../auditing/MongoTemplateAuditingTests.java | 2 +- .../ReactiveMongoTemplateAuditingTests.java | 2 +- .../AbstractMongoConverterUnitTests.java | 2 +- .../convert/CustomConvertersUnitTests.java | 2 +- .../core/convert/DataMongo273Tests.java | 2 +- .../DbRefMappingMongoConverterUnitTests.java | 2 +- .../DefaultDbRefResolverUnitTests.java | 2 +- .../DefaultMongoTypeMapperUnitTests.java | 2 +- .../convert/DocumentAccessorUnitTests.java | 2 +- .../core/convert/GeoConvertersUnitTests.java | 2 +- .../convert/GeoJsonConverterUnitTests.java | 2 +- .../LazyLoadingInterceptorUnitTests.java | 2 +- .../core/convert/LazyLoadingTestUtils.java | 2 +- .../convert/MappingMongoConverterTests.java | 2 +- .../MappingMongoConverterUnitTests.java | 2 +- .../MongoConvertersIntegrationTests.java | 2 +- .../convert/MongoConvertersUnitTests.java | 2 +- .../MongoCustomConversionsUnitTests.java | 2 +- .../convert/MongoExampleMapperUnitTests.java | 2 +- .../MongoJsonSchemaMapperUnitTests.java | 2 +- .../NamedMongoScriptConvertsUnitTests.java | 2 +- ...mberToNumberConverterFactoryUnitTests.java | 2 +- .../core/convert/ObjectPathUnitTests.java | 2 +- .../core/convert/QueryMapperUnitTests.java | 2 +- .../TermToStringConverterUnitTests.java | 2 +- .../core/convert/UpdateMapperUnitTests.java | 2 +- .../core/geo/AbstractGeoSpatialTests.java | 2 +- .../core/geo/GeoJsonModuleUnitTests.java | 2 +- .../data/mongodb/core/geo/GeoJsonTests.java | 2 +- .../core/geo/GeoSpatial2DSphereTests.java | 2 +- .../mongodb/core/geo/GeoSpatial2DTests.java | 2 +- .../core/geo/GeoSpatialIndexTests.java | 2 +- .../core/index/IndexFieldUnitTests.java | 2 +- .../core/index/IndexInfoUnitTests.java | 2 +- .../core/index/IndexingIntegrationTests.java | 2 +- ...entEntityIndexCreatorIntegrationTests.java | 2 +- ...PersistentEntityIndexCreatorUnitTests.java | 2 +- ...ersistentEntityIndexResolverUnitTests.java | 2 +- .../mongodb/core/index/PathUnitTests.java | 2 +- ...PersistentEntityIndexCreatorUnitTests.java | 2 +- .../mongodb/core/index/TextIndexTests.java | 2 +- .../data/mongodb/core/mapping/Account.java | 2 +- .../mongodb/core/mapping/AccountPojo.java | 2 +- .../data/mongodb/core/mapping/Address.java | 2 +- .../data/mongodb/core/mapping/BasePerson.java | 2 +- .../BasicMongoPersistentEntityUnitTests.java | 2 +- ...BasicMongoPersistentPropertyUnitTests.java | 2 +- .../mapping/CustomCollectionWithIndex.java | 2 +- .../mapping/DetectedCollectionWithIndex.java | 2 +- .../mongodb/core/mapping/GeneratedId.java | 2 +- .../core/mapping/GenericMappingTests.java | 2 +- .../core/mapping/GeoIndexedAppConfig.java | 2 +- .../mongodb/core/mapping/GeoIndexedTests.java | 2 +- .../mongodb/core/mapping/GeoLocation.java | 2 +- .../data/mongodb/core/mapping/Location.java | 2 +- .../mongodb/core/mapping/MappingTests.java | 2 +- .../mapping/MongoMappingContextUnitTests.java | 2 +- .../data/mongodb/core/mapping/Person.java | 2 +- .../core/mapping/PersonCustomCollection1.java | 2 +- .../core/mapping/PersonCustomCollection2.java | 2 +- .../core/mapping/PersonCustomIdName.java | 2 +- .../core/mapping/PersonMapProperty.java | 2 +- .../core/mapping/PersonMultiCollection.java | 2 +- .../core/mapping/PersonMultiDimArrays.java | 2 +- .../core/mapping/PersonNullProperties.java | 2 +- .../mongodb/core/mapping/PersonPojoIntId.java | 2 +- .../core/mapping/PersonPojoLongId.java | 2 +- .../core/mapping/PersonPojoStringId.java | 2 +- .../core/mapping/PersonSimpleList.java | 2 +- .../mongodb/core/mapping/PersonWithDbRef.java | 2 +- .../core/mapping/PersonWithObjectId.java | 2 +- .../mongodb/core/mapping/PrimitiveId.java | 2 +- .../AbstractMongoEventListenerUnitTests.java | 2 +- .../core/mapping/event/AfterSaveListener.java | 2 +- .../event/ApplicationContextEventTests.java | 2 +- ...ApplicationContextEventTestsAppConfig.java | 2 +- .../AuditingEntityCallbackUnitTests.java | 2 +- .../event/AuditingEventListenerUnitTests.java | 2 +- .../event/LoggingEventListenerTests.java | 2 +- .../event/PersonBeforeSaveListener.java | 2 +- .../event/SimpleMappingEventListener.java | 2 +- .../data/mongodb/core/mapping/event/User.java | 2 +- .../ValidatingMongoEventListenerTests.java | 2 +- .../mongodb/core/mapreduce/GroupByTests.java | 2 +- .../mapreduce/MapReduceCountsUnitTests.java | 2 +- .../core/mapreduce/MapReduceOptionsTests.java | 2 +- .../mapreduce/MapReduceResultsUnitTests.java | 2 +- .../core/mapreduce/MapReduceTests.java | 2 +- .../mapreduce/ReactiveMapReduceTests.java | 2 +- .../mongodb/core/mapreduce/ValueObject.java | 2 +- .../messaging/ChangeStreamTaskUnitTests.java | 2 +- .../core/messaging/ChangeStreamTests.java | 2 +- .../messaging/CursorReadingTaskUnitTests.java | 2 +- .../DefaultMessageListenerContainerTests.java | 2 +- ...aultMessageListenerContainerUnitTests.java | 2 +- .../core/messaging/SubscriptionUtils.java | 2 +- .../TailableCursorRequestUnitTests.java | 2 +- .../core/messaging/TailableCursorTests.java | 2 +- .../core/messaging/TaskFactoryUnitTests.java | 2 +- .../core/query/BasicQueryUnitTests.java | 2 +- .../mongodb/core/query/CriteriaTests.java | 2 +- .../mongodb/core/query/CriteriaUnitTests.java | 2 +- .../mongodb/core/query/FieldUnitTests.java | 2 +- .../mongodb/core/query/IndexUnitTests.java | 2 +- .../core/query/MetricConversionUnitTests.java | 2 +- .../query/MongoRegexCreatorUnitTests.java | 2 +- .../core/query/NearQueryUnitTests.java | 2 +- .../data/mongodb/core/query/QueryTests.java | 2 +- .../data/mongodb/core/query/SortTests.java | 2 +- .../core/query/TextCriteriaUnitTests.java | 2 +- .../mongodb/core/query/TextQueryTests.java | 2 +- .../core/query/TextQueryUnitTests.java | 2 +- .../query/UntypedExampleMatcherUnitTests.java | 2 +- .../data/mongodb/core/query/UpdateTests.java | 2 +- .../schema/JsonSchemaObjectUnitTests.java | 2 +- .../schema/JsonSchemaPropertyUnitTests.java | 2 +- .../core/schema/MongoJsonSchemaTests.java | 2 +- .../core/schema/MongoJsonSchemaUnitTests.java | 2 +- .../schema/ReactiveMongoJsonSchemaTests.java | 2 +- .../ExecutableMongoScriptUnitTests.java | 2 +- .../script/NamedMongoScriptUnitTests.java | 2 +- .../core/spel/ExpressionNodeUnitTests.java | 2 +- .../CriteriaValidatorUnitTests.java | 2 +- .../data/mongodb/gridfs/AntPathUnitTests.java | 2 +- .../gridfs/GridFsResourceUnitTests.java | 2 +- .../GridFsTemplateIntegrationTests.java | 2 +- .../gridfs/GridFsTemplateUnitTests.java | 2 +- .../ReactiveGridFsResourceUnitTests.java | 2 +- .../gridfs/ReactiveGridFsTemplateTests.java | 2 +- .../ReactiveGridFsTemplateUnitTests.java | 2 +- .../monitor/MongoMonitorIntegrationTests.java | 2 +- .../data/mongodb/monitor/Resumeable.java | 2 +- .../mongodb/performance/PerformanceTests.java | 2 +- .../performance/ReactivePerformanceTests.java | 2 +- ...tractPersonRepositoryIntegrationTests.java | 2 +- .../data/mongodb/repository/Address.java | 2 +- .../ComplexIdRepositoryIntegrationTests.java | 2 +- .../data/mongodb/repository/Contact.java | 2 +- .../mongodb/repository/ContactRepository.java | 2 +- .../ContactRepositoryIntegrationTests.java | 2 +- ...onvertingReactiveMongoRepositoryTests.java | 2 +- .../data/mongodb/repository/Credentials.java | 2 +- ...oRepositoryTextSearchIntegrationTests.java | 4 ++-- .../data/mongodb/repository/MyId.java | 2 +- .../data/mongodb/repository/Person.java | 2 +- .../mongodb/repository/PersonAggregate.java | 2 +- .../mongodb/repository/PersonExcerpt.java | 2 +- .../mongodb/repository/PersonRepository.java | 2 +- .../PersonRepositoryIntegrationTests.java | 2 +- ...RepositoryLazyLoadingIntegrationTests.java | 2 +- .../PersonRepositoryTransactionalTests.java | 2 +- .../mongodb/repository/PersonSummary.java | 2 +- .../mongodb/repository/PersonSummaryDto.java | 2 +- .../ReactiveMongoRepositoryTests.java | 2 +- .../repository/ReactivePersonRepository.java | 2 +- ...edeclaringRepositoryMethodsRepository.java | 2 +- .../RedeclaringRepositoryMethodsTests.java | 2 +- ...positoryIndexCreationIntegrationTests.java | 2 +- .../SampleEvaluationContextExtension.java | 2 +- .../SimpleReactiveMongoRepositoryTests.java | 2 +- .../data/mongodb/repository/SumAge.java | 2 +- .../data/mongodb/repository/User.java | 2 +- .../mongodb/repository/UserWithComplexId.java | 2 +- .../UserWithComplexIdRepository.java | 2 +- .../repository/UsernameAndPassword.java | 2 +- .../mongodb/repository/VersionedPerson.java | 2 +- .../cdi/CdiExtensionIntegrationTests.java | 2 +- .../repository/cdi/CdiPersonRepository.java | 2 +- .../repository/cdi/MongoTemplateProducer.java | 2 +- .../repository/cdi/RepositoryClient.java | 2 +- .../repository/cdi/SamplePersonFragment.java | 2 +- .../cdi/SamplePersonFragmentImpl.java | 2 +- .../cdi/SamplePersonRepository.java | 2 +- .../MongoNamespaceIntegrationTests.java | 2 +- ...RepositoriesRegistrarIntegrationTests.java | 2 +- ...sitoryConfigurationExtensionUnitTests.java | 2 +- ...RepositoriesRegistrarIntegrationTests.java | 2 +- ...sitoryConfigurationExtensionUnitTests.java | 2 +- ...ongoRepositoriesRepositoryConfigTests.java | 2 +- .../lazy/ClassWithNestedRepository.java | 2 +- ...estedMongoRepositoriesJavaConfigTests.java | 2 +- .../repository/custom/ComposedRepository.java | 2 +- ...ComposedRepositoryImplementationTests.java | 2 +- .../custom/CustomMongoRepository.java | 2 +- .../custom/CustomMongoRepositoryImpl.java | 2 +- .../custom/CustomReactiveMongoRepository.java | 2 +- .../CustomReactiveMongoRepositoryCustom.java | 2 +- .../CustomReactiveMongoRepositoryImpl.java | 2 +- ...ReactiveRepositoryImplementationTests.java | 2 +- .../CustomRepositoryImplementationTests.java | 2 +- .../repository/custom/RepositoryMixin.java | 2 +- .../custom/RepositoryMixinImpl.java | 2 +- .../query/AbstractMongoQueryUnitTests.java | 2 +- .../AbstractReactiveMongoQueryUnitTests.java | 2 +- .../ConvertingParameterAccessorUnitTests.java | 2 +- ...appingMongoEntityInformationUnitTests.java | 2 +- ...oParametersParameterAccessorUnitTests.java | 2 +- .../query/MongoParametersUnitTests.java | 2 +- .../query/MongoQueryCreatorUnitTests.java | 2 +- .../query/MongoQueryExecutionUnitTests.java | 2 +- .../query/MongoQueryMethodUnitTests.java | 2 +- .../query/PartTreeMongoQueryUnitTests.java | 2 +- .../ReactiveMongoQueryExecutionUnitTests.java | 2 +- .../ReactiveMongoQueryMethodUnitTests.java | 2 +- ...activeStringBasedAggregationUnitTests.java | 2 +- ...eactiveStringBasedMongoQueryUnitTests.java | 2 +- .../StringBasedAggregationUnitTests.java | 2 +- .../query/StringBasedMongoQueryUnitTests.java | 2 +- .../query/StubParameterAccessor.java | 2 +- ...nsuringQueryCreationListenerUnitTests.java | 2 +- .../MongoRepositoryFactoryBeanUnitTests.java | 2 +- .../MongoRepositoryFactoryUnitTests.java | 2 +- ...ongoPredicateExecutorIntegrationTests.java | 2 +- .../QuerydslRepositorySupportTests.java | 2 +- ...veQuerydslMongoPredicateExecutorTests.java | 2 +- .../support/SimpleMongoRepositoryTests.java | 2 +- .../SimpleMongoRepositoryUnitTests.java | 2 +- ...leMongoRepositoryVersionedEntityTests.java | 2 +- ...impleReactiveMongoRepositoryUnitTests.java | 2 +- ...veMongoRepositoryVersionedEntityTests.java | 2 +- .../SpringDataMongodbSerializerUnitTests.java | 2 +- .../test/util/AfterTransactionAssertion.java | 2 +- .../data/mongodb/test/util/AssertErrors.java | 2 +- .../data/mongodb/test/util/Assertions.java | 2 +- .../mongodb/test/util/BasicDbListBuilder.java | 2 +- .../data/mongodb/test/util/CleanMongoDB.java | 2 +- .../util/CleanMongoDBJunitRunListener.java | 2 +- .../mongodb/test/util/CleanMongoDBTests.java | 2 +- .../data/mongodb/test/util/Client.java | 2 +- .../mongodb/test/util/DocumentAssert.java | 2 +- .../test/util/EnableIfMongoServerVersion.java | 2 +- .../util/EnableIfReplicaSetAvailable.java | 2 +- .../test/util/MongoClientExtension.java | 2 +- .../mongodb/test/util/MongoExtensions.java | 2 +- .../test/util/MongoServerCondition.java | 2 +- .../test/util/MongoTemplateExtension.java | 2 +- .../mongodb/test/util/MongoTestTemplate.java | 2 +- .../util/MongoTestTemplateConfiguration.java | 2 +- .../mongodb/test/util/MongoTestUtils.java | 2 +- .../data/mongodb/test/util/MongoVersion.java | 2 +- .../mongodb/test/util/MongoVersionRule.java | 2 +- .../test/util/ReactiveMongoTestTemplate.java | 2 +- .../data/mongodb/test/util/ReplSetClient.java | 2 +- .../data/mongodb/test/util/ReplicaSet.java | 2 +- .../data/mongodb/test/util/Template.java | 2 +- .../data/mongodb/util/json/BsonUtilsTest.java | 2 +- .../ParameterBindingJsonReaderUnitTests.java | 2 +- .../data/mongodb/core/Entities.kt | 2 +- ...ableAggregationOperationExtensionsTests.kt | 2 +- .../ExecutableFindOperationExtensionsTests.kt | 2 +- ...xecutableInsertOperationExtensionsTests.kt | 2 +- ...utableMapReduceOperationExtensionsTests.kt | 2 +- ...xecutableRemoveOperationExtensionsTests.kt | 2 +- ...xecutableUpdateOperationExtensionsTests.kt | 2 +- .../core/MongoOperationsExtensionsTests.kt | 2 +- ...tiveAggregationOperationExtensionsTests.kt | 2 +- ...iveChangeStreamOperationExtensionsTests.kt | 2 +- .../ReactiveFindOperationExtensionsTests.kt | 2 +- .../ReactiveInsertOperationExtensionsTests.kt | 2 +- ...activeMapReduceOperationExtensionsTests.kt | 2 +- .../ReactiveMongoOperationsExtensionsTests.kt | 2 +- .../ReactiveRemoveOperationExtensionsTests.kt | 2 +- .../ReactiveUpdateOperationExtensionsTests.kt | 2 +- .../core/query/CriteriaExtensionsTests.kt | 2 +- .../mongodb/core/query/KPropertyPathTests.kt | 2 +- .../query/TypedCriteriaExtensionsTests.kt | 2 +- .../CoroutineRepositoryUnitTests.kt | 2 +- .../repository/KotlinRepositoryUnitTests.kt | 2 +- ...ctiveMongoQueryMethodCoroutineUnitTests.kt | 2 +- src/main/asciidoc/index.adoc | 2 +- 943 files changed, 1007 insertions(+), 1007 deletions(-) diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java index c7df157f63..79e64ff4be 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/ProjectionsBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java index 5694416f3d..83eeec9eab 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/DbRefMappingBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java index a29fb51e3e..0941d9c0ac 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java index 4c09f1a166..5c99c07fa6 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/AbstractMicrobenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java index e6d728dbdc..8d3e57eecc 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/HttpResultsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java index 19e7987ee2..4167d3c01d 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/MongoResultsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java index bc43cb5ded..c55e10daaa 100644 --- a/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java +++ b/spring-data-mongodb-benchmarks/src/main/java/org/springframework/data/mongodb/microbenchmark/ResultsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java index eee31a1e67..03fadff0fe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java index 46c1c43546..fae652c7f4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ClientSessionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java index 81d0955f0a..60b2027763 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/CodecRegistryProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java index 4d5831dd4d..89e035ae69 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/InvalidMongoDbApiUsageException.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java index 0ec364f6c8..855a59c55d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java index 4167250634..3d85a33dcb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java index 96620d8f8a..612c3eeb3e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index 3992861468..ba8efa536c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index aa46fbc882..9356a9e7d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java index c1b80f814f..90a3b32023 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java index 47cd65a1c8..79a68e83ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java index 746a769e22..b2a998548a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java index b0c8d640f7..1e6013d73d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java index 6a54e94e65..eba2aceb9f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java index 6138d71a57..711947a30d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java index 34301bdc6f..b1f1c06d08 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java index 8792e169cc..63706eff8a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -110,7 +110,7 @@ public ReactiveMongoTransactionManager(ReactiveMongoDatabaseFactory databaseFact this.options = options; } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doGetTransaction(org.springframework.transaction.reactive.TransactionSynchronizationManager) */ @@ -123,7 +123,7 @@ protected Object doGetTransaction(TransactionSynchronizationManager synchronizat return new ReactiveMongoTransactionObject(resourceHolder); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#isExistingTransaction(java.lang.Object) */ @@ -132,7 +132,7 @@ protected boolean isExistingTransaction(Object transaction) throws TransactionEx return extractMongoTransaction(transaction).hasResourceHolder(); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doBegin(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object, org.springframework.transaction.TransactionDefinition) */ @@ -175,7 +175,7 @@ protected Mono doBegin(TransactionSynchronizationManager synchronizationMa }); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doSuspend(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object) */ @@ -192,7 +192,7 @@ protected Mono doSuspend(TransactionSynchronizationManager synchronizati }); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doResume(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object, java.lang.Object) */ @@ -203,7 +203,7 @@ protected Mono doResume(TransactionSynchronizationManager synchronizationM .fromRunnable(() -> synchronizationManager.bindResource(getRequiredDatabaseFactory(), suspendedResources)); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doCommit(org.springframework.transaction.reactive.TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction) */ @@ -243,7 +243,7 @@ protected Mono doCommit(TransactionSynchronizationManager synchronizationM return transactionObject.commitTransaction(); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doRollback(org.springframework.transaction.reactive.TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction) */ @@ -268,7 +268,7 @@ protected Mono doRollback(TransactionSynchronizationManager synchronizatio }); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doSetRollbackOnly(org.springframework.transaction.reactive.TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction) */ @@ -282,7 +282,7 @@ protected Mono doSetRollbackOnly(TransactionSynchronizationManager synchro }); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doCleanupAfterCompletion(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object) */ @@ -509,7 +509,7 @@ private ClientSession getRequiredSession() { return session; } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.support.SmartTransactionObject#isRollbackOnly() */ @@ -518,7 +518,7 @@ public boolean isRollbackOnly() { return this.resourceHolder != null && this.resourceHolder.isRollbackOnly(); } - /* + /* * (non-Javadoc) * @see org.springframework.transaction.support.SmartTransactionObject#flush() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java index 621a5389e3..da48f22154 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java index f32d0f593e..2223b82391 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java index cc3004644f..dbbf146fc1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java index fc2079ba8c..1148227786 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/UncategorizedMongoDbException.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index a9635c9743..96df484aad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java index f02fbaabf0..a2a1f74b08 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java index 3bb71c86ab..dd32d9bb70 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/BeanNames.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java index 3fd9017ef9..2141063afc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java index e934dc2114..022ddb3036 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java index d7e6b2033e..c67d2cd833 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java index d93c11466d..dcfe70b367 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GeoJsonConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java index 1b03d777bc..d6653e8999 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/GridFsTemplateParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java index 767c03e3af..0e825afe1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java index fb3ac7408e..241080afb1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java index eb6366d2a6..ff73015899 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java index b3dcfdabce..91b89593c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index a96617de46..7dd481d57a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java index 39f17c4142..5991a683ef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java index c929b5b3a6..d4e1c65358 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java index 93248e2f3f..8486f28864 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoJmxParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java index 2516ca70e4..5bdb199a50 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index 7ed91b27f9..cd4d16d91b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. @@ -45,7 +45,7 @@ private MongoParsingUtils() {} /** * Parses the {@code mongo:client-settings} sub-element. Populates the given attribute factory with the proper * attributes. - * + * * @param element * @param mongoClientBuilder * @return diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java index 65aa04745f..dc02a1eee4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoTemplateParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java index b2045db43b..ba382a32cc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java index 20f7d16602..01123cb7d6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java index ed5d73d6e6..c7b6479a24 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java index 87174f28c0..acf952069f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadPreferencePropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java index 2865248eac..5e5d82f6be 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java index 141c874ffc..359e165061 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/StringToWriteConcernConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java index 2499ecc48b..5e9e6b39ee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/UUidRepresentationPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java index e1b1531e15..7bb77d8d8c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java index 2cebf65312..adb2e1d8ba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/AggregationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java index bbc85032ec..f214ff3d4b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java index a86dbc903f..55a65a2baa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java index 65f27f915f..a4f6f7e226 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java index d6b9bcc6e3..5c79cffd6c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. 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 8e4f1b1f48..ca61d18d96 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java index 66b6a37b85..ec7104c9de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CountQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java index bb98bb96bd..dd68932c3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CursorPreparer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java index d828e962e5..8e9aa3522b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DbCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java index fb3d3fcf26..f4d72f648b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java index 62ad1f46ee..010f494f6a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java index 3888b0549b..0bab23dead 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperationsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java index 2ec7c14c95..832d91a1a7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java index 53e217f3eb..309b064310 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultScriptOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java index 459792e11a..037d54b213 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultWriteConcernResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java index aa97063703..d0e1f81143 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DocumentCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index db1d04d244..7effa25abd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java index 4e9bec35e3..f2bc624923 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java index 0317b01890..c45ad0404d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableAggregationOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index 3bd63bb4f9..28dd7dddcc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java index 758112ef96..c196babfa0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java index 2827f770cb..33df93edf4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java index fe4a0a8ea3..3565aad04c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableInsertOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java index be43d25a85..e3f9601251 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java index 96f581d55f..84e035977f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableMapReduceOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -36,7 +36,7 @@ class ExecutableMapReduceOperationSupport implements ExecutableMapReduceOperatio private final MongoTemplate template; ExecutableMapReduceOperationSupport(MongoTemplate template) { - + Assert.notNull(template, "Template must not be null!"); this.template = template; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java index 5c95c469e2..08024935ae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java index 7b39522066..7cc90b4676 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index 7b45b10680..a8b58669e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java index f5ed3740eb..0a57d77458 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java index ac8f45d05f..30a3ed9e5f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndModifyOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java index 2de66015c2..6122837a27 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java index 3f603f9f48..0628db7d9c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindPublisherPreparer.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java index 7fbd49359e..ff2d8a1be1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FluentMongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java index 0d3b648289..6f17a3026c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/GeoCommandStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java index 7e574c6944..e7fae4df5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java index 2c14a5bafd..340c11bb99 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. 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 fdc7247ee7..ecbf8a4f07 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 @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java index c47cc04941..dd881f9312 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java index 9662e31b2c..dbc688d94b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoActionOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java index e198368927..1e3465cd8b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java index f28113cc5a..415fba76b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdminOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index 7c281c7bf6..22194a451a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java index 2c66fe3813..162035a45d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java index f9cc9d5e8d..ee3608e8ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java index 9762550066..dac4b0d6d7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index f85dd8e1fd..bc0e39bbc9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java index 555913c548..907e180d13 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoEncryptionSettingsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index e34950375a..4c7d090f7c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java index 2757ba2c31..f3c0dcd624 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index b1c5d3ee48..5a5a3b7fc5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. 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 050d8dd876..3955d860d8 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java index f84bba4c20..5eb9f110b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/PropertyOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index 659db0811f..67ac4fede6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java index e2a4743a40..279bb4fd52 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java index 77c688c77f..35c8052e72 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveAggregationOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java index eab988c5ab..279f4184fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java index 691a6e256c..25d23322a0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java index f59ed5e60e..a83d1186d0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveCollectionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java index cc36e0358b..1e03b5cdd1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveDatabaseCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index d9cdb3f257..b66f6e176d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java index 37aa0d38f0..9e8dc8d8b2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java index 631568e4a3..0e6627f2b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFluentMongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java index c9801da417..6af602a01a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java index bc7eab0cc5..928c4426a5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveInsertOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java index 34a41cdc56..105e85b005 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java index e76417bebe..3ff586652e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMapReduceOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java index c58292673c..8177e2d7e9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java index c62bd5c54f..fd7ea5ab7a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java index 8cd27a2bbd..b91ba4954d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 94fc8843f8..2d981fd1b4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index d04f0805d4..76afa855a1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java index 499592a437..dbe3386df9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java index 98ef34a784..3cb11c0626 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveRemoveOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java index 084c2ce9f5..c9b15324fc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java index 8babbe3ae0..17c17edd24 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java index 74aa29799a..60e7a5ba89 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java index d723e1e337..598f691b1d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java index fa2e16b082..6aefb78cd5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReadPreferenceAware.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java index e076c09bf4..24ad1c5ffc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java index 5c58121f77..c12d4b1005 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java index 3b03afa5ce..ead52ee15e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java index b665128a0c..df7a4b5a4c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java index 08c69af2b0..3ce3ce5774 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java index 98c4003c5c..337109c349 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java index f2434735a3..c7852b60b9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteConcernResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java index 3183bf92ba..2f88e8c14c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/WriteResultChecking.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java index 449c137b7e..3f3dd125d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. @@ -99,7 +99,7 @@ public AddFieldsOperationBuilder and() { return new AddFieldsOperationBuilder(getValueMap()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.DocumentEnhancingOperation#mongoOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index df75781255..cecc8f2554 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java index 7e15a70284..2a0148cc5d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java index 635f00abec..3c659f166f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationExpressionTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java index 4c7f687663..9e26c3e6f6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationFunctionExpressions.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java index b22458ad94..54a3786ba2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java index b86407edbb..d033aba3de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -107,7 +107,7 @@ default Fields getFields(Class type) { * This toggle allows the {@link AggregationOperationContext context} to use any given field name without checking for * its existence. Typically the {@link AggregationOperationContext} fails when referencing unknown fields, those that * are not present in one of the previous stages or the input source, throughout the pipeline. - * + * * @return a more relaxed {@link AggregationOperationContext}. * @since 3.0 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java index eebba56434..cc7ffbdc55 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 2c500149da..c69e75e3ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java index 1421db76a9..cf261d2b97 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java index fd14b1a0b8..5170986f93 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java index 0556410c89..14fa8c48d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index 6efc28106b..e69531e036 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java index d729b9dfaf..6a62379185 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java index 5a982c06f8..dba40d94d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java index 3f2d733470..235c16befe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -108,7 +108,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), options); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java index 67cdbe2ee5..173fa4ece5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -104,7 +104,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), options); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java index feee4422e2..6a768a6172 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java index 70bda575e7..4e5c364db9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ComparisonOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java index 5c9d1f3b92..1d3890ce89 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java index 7d273dc751..315a463e1f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java index 8ac0d45b62..e2b65aa7ff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java index 0a650dc0dc..51f570d61c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentEnhancingOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. @@ -71,7 +71,7 @@ public Document toDocument(AggregationOperationContext context) { */ protected abstract String mongoOperator(); - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java index fa09bf3028..c72abd636a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFields.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java index f0c2b60a26..b1db4fb262 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java index 77fe14854d..118965b7c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FacetOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -86,7 +86,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), facets.toDocument(context)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java index 2e0ba33071..5fdced5e41 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java index 1daeafa32d..1ab2d30763 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Fields.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java index de8752d589..7fd95d2c6f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/FieldsExposingAggregationOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java index 83468abb1a..56d87f6d45 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java index abf7ff393c..f71e2b14b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GraphLookupOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java index b221e9ba2d..cd14d89ed0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/InheritingExposedFieldsAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java index e41363b233..e3c6a73537 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -52,7 +52,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), Long.valueOf(maxElements)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java index 7be63c33ee..5a4c8cbee4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LookupOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -86,7 +86,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), lookupObject); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index 8f2f0aa288..c9d83ae6c8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -57,7 +57,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), context.getMappedObject(criteriaDefinition.getCriteriaObject())); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java index 05e01e4fcf..8dc1d09f38 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MergeOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. @@ -125,7 +125,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), $merge); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java index 0aef6af3cd..d067d6e208 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ObjectOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -118,7 +118,7 @@ public MergeObjects mergeWithValuesOf(AggregationExpression... expression) { * Creates new {@link ObjectToArray aggregation expression} that takes the associated value and converts it to an * array of {@link Document documents} that contain two fields {@literal k} and {@literal v} each.
      * NOTE: Requires MongoDB 3.6 or later. - * + * * @since 2.1 */ public ObjectToArray toArray() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java index 4eaa669667..de424dfebd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -213,7 +213,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), $out); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java index a9d384e108..5ae8c4caa5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index 82a1de69d1..d2f173e90b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java index 3428b64bbc..f16865b251 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RedactOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. @@ -77,7 +77,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), condition.toDocument(context)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java index 2c53c275a7..fae573e822 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/RelaxedTypeBasedAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index c891a73e42..c452ffb8ea 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -86,7 +86,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document("$replaceRoot", new Document("newRoot", getReplacement().toDocumentExpression(context))); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java index 9fb7249e4b..0d53dbf5cf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java index b1c3bf4ceb..fbfc680484 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SampleOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. @@ -51,7 +51,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), new Document("size", this.sampleSize)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java index 3fde9da6a2..0c0a7e527e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ScriptOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index cd06098fe6..731668ed3c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -99,7 +99,7 @@ public FieldAppender and() { return new FieldAppender(getValueMap()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.DocumentEnhancingOperation#mongoOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java index 2fbbc7209e..b72a024f8d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -55,7 +55,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), skipCount); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java index a631b08627..f480d55305 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortByCountOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. @@ -78,7 +78,7 @@ public Document toDocument(AggregationOperationContext context) { : groupByExpression.toDocument(context)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java index 5b5cce4588..f4441b73b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. @@ -78,7 +78,7 @@ public Document toDocument(AggregationOperationContext context) { return new Document(getOperator(), object); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java index a21223ee35..33b5c72c78 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java index d97ed924b7..5a31f6b3fc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -1387,7 +1387,7 @@ public LTrim charsOf(String fieldReference) { /** * Optional specify the {@link AggregationExpression} evaluating to the character sequence to trim from the * beginning. - * + * * @param expression must not be {@literal null}. * @return new instance of {@link LTrim}. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java index a3158e18d5..5cb633740e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java index 7c7fbb1c67..d4967cf000 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypedAggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java index 2ebddfd68e..9c1beb1dbd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnionWithOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java index b42cef2a69..11bf850c9d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnsetOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -124,7 +124,7 @@ public Document toDocument(AggregationOperationContext context) { fields.stream().map(it -> computeFieldName(it, context)).collect(Collectors.toList())); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java index 11e4dcaea5..8b8d1695f5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java index 3233c30233..55baacba78 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java index 41066052d3..91380271b2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/CustomConversions.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java index e4f14fe935..78f59e7a85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefProxyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java index 18b2695e92..da26f4cce6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java index 437426db49..2ac0fd28ee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java index e3a66c020b..3540c97439 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefProxyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 02c9e9c2d1..8b6674460c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java index 5bd182ca94..ad4eb85dfd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. 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 606221deb4..ae090a0ed5 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java index 9522a60ce6..13234cc3ab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java index e3b1d98925..8ed11e2851 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPropertyAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java index 4437a95d3a..5425051fc6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java index 8b1800bb3e..b60dc00172 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/JsonSchemaMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java index 1448544f27..a04a100cc5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. 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 24ac181711..92f7617833 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index 5086f30401..5bf48cd3f5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java index 0db28c31f0..7e4b37cd83 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java index aa96f9cab6..9f1925f6e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java index 884a1a96a2..606cb03e8b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java index d2896280e0..34b9479196 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoJsonSchemaMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java index 83069f38d7..a65aee3848 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoTypeMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java index c11ebd80fb..d3115a4400 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java index f9262f8b3b..8cb28bfe14 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java index 6af70e6c2d..3b5bf73efa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ObjectPath.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 14f25c8843..0fb8723d11 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java index afe13f472a..c824148ddb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java index 0fa9429e4c..43d8cdc09a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ValueResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java index 5c07fb8d1b..3c659f7cc1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java index 7cbcc8ccc5..2061980734 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java index afb2370f3e..ed88220fff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java index 4acb111c3d..498317a80a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java index 49d886ddcc..ba8cabc8e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java index 3bd81c207e..f42d38e0dc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java index 32f4e26ecf..881025497b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java index 3086df003d..efcb393d9b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java index 0f68ac4f45..685284e91d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java index 612be9a813..309f493f02 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Sphere.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java index 373992c99a..fa759e7a74 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java index de137b21bf..50c5b37ed4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java index 4dae271d33..de1e9cf43f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndexes.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java index 9f76746b60..b692aca2fa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/DurationStyle.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java index be56df5e9b..f293dff842 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexType.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java index 9da7562406..6ece161258 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java index 997d962ac2..3ca3d2d8ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java index 071b8f48cc..95652b0dba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java index 4fe5093d6a..4d93100fe0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/HashedIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java index 6a7807ef31..1ca2711665 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java index 0051954a8d..20456cd729 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java index 28d15553c2..06529c508f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexDirection.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java index 57a7912f10..d0a1da68ea 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java index 77689cfccb..5edf898c51 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java index 99bbb2089b..7b507a8727 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java index 7ea6fbbd23..385609ece5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java index a64257af22..54ef23af51 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java index ec686a6189..4f003e2075 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexOperationsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java index cb84c72ddf..5a8c354c30 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexPredicate.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java index 4200535cd0..e2137ac047 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java index 8f2199c93d..31a21e09d9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. @@ -47,7 +47,7 @@ /** * The index sort direction. - * + * * @return {@link IndexDirection#ASCENDING} by default. */ IndexDirection direction() default IndexDirection.ASCENDING; @@ -175,7 +175,7 @@ /** * Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}.
      * Must not be used with {@link #sparse() sparse = true}. - * + * * @return empty by default. * @see https://docs.mongodb.com/manual/core/index-partial/ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java index 00a1315760..80fabb676d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java index 6c37cfedda..bcfe92e6b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index 6d3b2b612a..224aca249b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java index 0286095902..a90514daf0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java index 68977a99eb..596aa1f0c6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveIndexOperationsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java index b4e7337150..6a3f6470ee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java index 101694f4d6..9386382be1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java index 58d510be8b..9b37d4f9d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/TextIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index 74a2d08027..44daa6bcaa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index e4de736c54..0b47c79d04 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java index d0c1aad819..7af678541b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. @@ -90,7 +90,7 @@ public String getFieldName() { return this.fieldName; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty#getFieldType() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java index b7d524be86..9e591590ed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DBRef.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java index c1ffd8c6c9..1575be7d29 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Document.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java index 2fd2218fc3..45e8b815fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. 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 3fd884e0fe..5a03040e74 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java index 0b50ee7b7f..22eb3244f6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Language.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java index 15241cacc5..12a4ad8504 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoId.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index 239fb4b1cf..938f16d0fa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java index 15c470538f..9a0d60100b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index 7d6db37c0f..53a5eb7f91 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java index 4a999ce08b..95f2b831ff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java index 2a93205244..74cde4d5a0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardKey.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java index 514475982a..df6bf27525 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Sharded.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java index 922342c497..68f7ebdc24 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ShardingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java index 5f1af082ad..de39836eed 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TextScore.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java index 6cb5af5e3f..5b43b5e573 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java index 2fbfbf5175..e580f1c076 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java index 7ff740a42d..8e7d94d0bb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java index 4eb6a22117..34032a9697 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java index 27192183af..c4fc869e6b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java index 42c6da2d49..15577955ef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java index bd2152dabf..d1f1f0ef6c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java index a82041802e..1b4fea3322 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java index 0d25bb2a46..9e4e473120 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEntityCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -45,7 +45,7 @@ public AuditingEntityCallback(ObjectFactory auditingH this.auditingHandlerFactory = auditingHandlerFactory; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback#onBeforeConvert(java.lang.Object, java.lang.String) */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java index 2b1b0d3f78..48f663a747 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AuditingEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java index 9b512b0e26..ae81dcf2c6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java index c5e2366f23..167bebac29 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java index f1ed6db97d..37f08e6e2e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java index 2c83125085..0201400809 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java index 601676043d..f38bf68a11 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java index b7c8a694ed..2f0d4f5247 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/LoggingEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java index 58150baf94..ab2fa3ac85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/MongoMappingEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java index 5ff16dd3d3..90972d81c1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java index 81a209d303..f90ea1f3db 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java index 4c1e9146fa..ed01158604 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java index 1590848008..d10545154b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java index b8001e2f2a..3815eb4faa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java index d53ae30e19..d62831d6ab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ValidatingMongoEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java index 8fc42d2bc3..b028ab42e4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupBy.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java index 0c5455a9d5..a93e67ee12 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/GroupByResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java index 546814efd6..92ec228c75 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceCounts.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java index 0afd09f708..414d602a41 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java index d53c9b2573..2936aff725 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java index 979f6326db..bb99076031 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTiming.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java index ed80383294..db3e767cf1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Cancelable.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java index bc104fe327..b552cb335c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java index 2ae3fd92f8..d609e9b6e6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java index 4056367525..22b924ff28 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/CursorReadingTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java index db84b553b1..ce0e987e3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java index 50c47a679f..221f486cd8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/LazyMappingDelegatingMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -37,7 +37,7 @@ class LazyMappingDelegatingMessage implements Message { this.converter = converter; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.messaging.Message#getRaw() */ @@ -46,7 +46,7 @@ public S getRaw() { return delegate.getRaw(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.messaging.Message#getBody() */ @@ -71,7 +71,7 @@ public T getBody() { String.format("No converter found capable of converting %s to %s", messageBody.getClass(), targetType)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.messaging.Message#getProperties() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java index 2024d0b527..019ce13180 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java index 224e4a48a8..08fc44f1f1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java index 9a43376dc9..8959405fff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/MessageListenerContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java index 1907e4442c..6d9e1cbdd1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SimpleMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java index 1dd267db4f..988545cd3d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Subscription.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index a6d1d28d23..1b74bf59df 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java index 0c1bb60ec7..96d88456ef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java index f4e0c2145a..092eebfb7c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -45,7 +45,7 @@ public TailableCursorTask(MongoTemplate template, TailableCursorRequest reque queryMapper = new QueryMapper(template.getConverter()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.messaging.CursorReadingTask#initCursor(org.springframework.data.mongodb.core.MongoTemplate, org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions, java.lang.Class) */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java index 28ddf348fd..85c2ee0c02 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/Task.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java index eb37ab93c2..0b1e2fcb8e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TaskFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java index 8a6b740451..4de789e12f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java index 9d1693f210..1cb12fa0c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java index 191ba34ccf..ca62bb6c3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Collation.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 364af00935..7f8ec91fe3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java index 2913fdbbfe..0c589da10c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/CriteriaDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java index 8c822e7156..32ab4e4339 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java index 5217fb756a..57a233eb44 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. 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 bf48a9f5bb..2bfddfa2cd 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-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java index 5958b3e3ee..42870eaddc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java index f81b561726..5913bcb28b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java index f37347efca..b8da598b73 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/NearQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. 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 e509ea7a5e..1f54e7049d 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-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java index 916858e7f8..572083dcbb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/SerializationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java index f7504a417c..1b478b193c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Term.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. @@ -93,7 +93,7 @@ public String getFormatted() { return negated ? negateRaw(formatted) : formatted; } - /* + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -114,7 +114,7 @@ public boolean equals(Object o) { && ObjectUtils.nullSafeEquals(raw, term.raw); } - /* + /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ @@ -130,7 +130,7 @@ public int hashCode() { return result; } - /* + /* * (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java index 424a40813b..ad66db43b0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextCriteria.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. @@ -232,7 +232,7 @@ public Document getCriteriaObject() { return new Document("$text", document); } - /* + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @@ -253,7 +253,7 @@ public boolean equals(Object o) { && ObjectUtils.nullSafeEquals(diacriticSensitive, that.diacriticSensitive); } - /* + /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java index 0560b5d384..9a72b3ffc0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java index 78101570b5..cc821fe68f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UntypedExampleMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index cf2d14efd7..34cab18c31 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java index 05660e7d0f..16ffa8be51 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/UpdateDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java index 1c736fcda0..1b05840913 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -30,7 +30,7 @@ class DefaultMongoJsonSchema implements MongoJsonSchema { private final JsonSchemaObject root; DefaultMongoJsonSchema(JsonSchemaObject root) { - + Assert.notNull(root, "Root must not be null!"); this.root = root; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java index 15a9c5aa10..2788dd59e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -29,7 +29,7 @@ class DocumentJsonSchema implements MongoJsonSchema { private final Document document; DocumentJsonSchema(Document document) { - + Assert.notNull(document, "Document must not be null!"); this.document = document; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java index d87247f616..28116e1bac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java index c564979858..4ad64e77bb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -429,7 +429,7 @@ static Type jsonTypeOf(String name) { /** * Create a {@link Type} with its default {@link Type#representation() representation} via the name. - * + * * @param name must not be {@literal null}. * @return the matching type instance. * @since 2.2 @@ -474,7 +474,7 @@ static Set bsonTypes() { /** * Get the {@literal bsonType} representation of the given type. - * + * * @return never {@literal null}. * @since 2.2 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java index 68f0f94c47..d85e4fa86b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/JsonSchemaProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java index ea7bf542e1..d45dcd09ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java index 48e9540ecd..2486e98e08 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java index ea475ef72d..099f4ee6aa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/UntypedJsonSchemaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java index cb076c42f3..9570b5380f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/ExecutableMongoScript.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java index 029d718c90..98337dcacb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/script/NamedMongoScript.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java index 560691a3d6..147281f7fd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java index 93270f2b5e..9ee06223e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformationContextSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java index 978b6e9c95..d35ed2800a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java index 68c0bb10f7..79b4a31d89 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/LiteralNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 92fb194769..5a2c48bc20 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java index 3bee4d7905..d918aff345 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. 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 index 6e20aae77e..72d82d7981 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java index 74f75b3e33..8edb4fec59 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/DocumentValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java index 01f766892a..a0e152d9fe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/JsonSchemaValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java index 0b9d131b01..8b55f431e6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/Validator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java index df2ef261bb..6d016fab3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AntPath.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java index 712c816ef2..074698f6e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsCriteria.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java index fd158b82b4..50a3041a2c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java index bd5709ef5a..9be40a4a5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java index 2fa73a303a..cd7c958646 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsOperationsSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java index a37ba34a06..1e44844a95 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 57b8b7df80..c45c9b459a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java index 3d2405759b..7216aa5995 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsUpload.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java index ae2f2e1078..86507a7d8e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java index 411fc2a2d1..e2481e1649 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java index 16540e1a3d..bf9dc42aac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java index 9decedc78e..c752399b9b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsUpload.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java index e9c1b00b74..9e7b1854de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java index 220bcadd3f..e3de09cfc4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java index 9a502cb74a..5cadfc0c1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java index d7480a6e12..482a511342 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java index ae453fd1d1..944f6a59b9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java index eb2f0d6afc..045348271d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java index 7916fbdc27..1e3eef5850 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java index 4516d5e00e..b116f1d01b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java index 4982e569c4..a76e406510 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java index 5b6c908b6d..8f1e5afbef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Aggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java index 36eb77397e..c0b3de1e57 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/CountQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java index 598941b99f..6e347e3eff 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/DeleteQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java index 04b3c0225f..5ed9456d27 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ExistsQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. 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 50288a1f73..79987b5829 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 @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java index 88f7d11f7d..144bb23afa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java index bf23f33801..37c17ecb5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Near.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java index d86e543335..6b43098456 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java index 1a45a11bdb..ac9a8900f3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java index c018fa29bc..bb5635c312 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Tailable.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java index 576013fdfe..d4639d9c8b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java index 63d6fbaaa6..7bb9dfa237 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/cdi/MongoRepositoryExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java index 7b6ed5bdb9..a4165d522f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableMongoRepositories.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -134,7 +134,7 @@ /** * Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the * repositories infrastructure. - * + * * @return {@literal false} by default. */ boolean considerNestedRepositories() default false; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java index 7b0d540211..3e8873bb74 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/EnableReactiveMongoRepositories.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. @@ -136,7 +136,7 @@ /** * Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the * repositories infrastructure. - * + * * @return {@literal false} by default. */ boolean considerNestedRepositories() default false; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java index 8923d08f48..4b44e42306 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java index 60ec8f4c5b..6996d49e66 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java index af01fb2498..02a00a52cd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/MongoRepositoryConfigurationExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java index b4335bc3e3..063e7c9e1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoriesRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java index 936ad35265..f6de4a02b4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/config/ReactiveMongoRepositoryConfigurationExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java index 376ba31b9e..f768cf5457 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java index c451cfce7f..a96dbed67f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java index e04e7945aa..8a8ffa0542 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java index b2e660ab7d..8c52392a3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/BooleanUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java index 724cf2689d..579b618a2b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/CollationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java index 30ce2e81ac..a880a1c05e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java index cd154b5bd7..ff3ab1e72d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DefaultSpELExpressionEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java index bb1d112099..de64dc721a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/DtoInstantiatingConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java index 9dd2bdc12d..a99b542527 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. @@ -75,7 +75,7 @@ default boolean hasCollation() { /** * Return the collation for the entity or {@literal null} if {@link #hasCollation() not defined}. - * + * * @return can be {@literal null}. * @since 2.2 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java index 44cf42f9d4..488f1ca5d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoEntityMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -34,7 +34,7 @@ public interface MongoEntityMetadata extends EntityMetadata { /** * Returns the {@link MongoPersistentEntity} that supposed to determine the collection to be queried. - * + * * @return * @since 2.0.4 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java index 1dc153398b..a934d6fcc3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java index a33b5df063..1e2ac33f1b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java index 483b806939..a1b6a8f2e4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java index 529d12307b..24e5033a67 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index facc461f5f..237b878975 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. 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 a2ec157f19..e97dae204c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java index 902a364643..479be5e8f2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java index 5b68f79bfb..596364bc26 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java index f95d5cf5ef..306ec6a3a3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoParameterAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 66fe7c8492..7753daf3eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java index 4659653bfd..08c563ae2c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java index 8ac8dbad1b..aa1b34dea1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactivePartTreeMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java index cacf351d06..95e0465258 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java index 43ef9374b2..2ccd20e441 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java index 48d35a1041..37ba539923 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/SimpleMongoEntityMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java index ecbbfa0588..4deb7d0d52 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index fb86830f48..fb721a3be4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java index a30833b4d3..a3ae4a6b88 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/CachingExpressionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java index 0703c33ecc..7464ed41ac 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java index 426ba97fad..04cb3d890a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java index 58e3cb5985..b9ac39efad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoAnnotationProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java index 10033c1ead..28d06fb1a4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java index ea0ba55db1..699e7b158d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java index 040f2dee77..840527e4a9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java index 1b3c726f07..3f0d281cc4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java index 95f8dc4fd2..422eea5778 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java index 10962ce279..3ba84a2dd3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. @@ -31,7 +31,7 @@ * 2.0. *

      * Modified for usage with {@link QuerydslAbstractMongodbQuery}. - * + * * @param query type * @author tiwe * @author Mark Paluch diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java index 6bde6ca208..36057d58c9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java index dbaa44900d..344ad08826 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java index e329814780..0c695afd0c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java index 7f5c87c585..95d2299670 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java index 107e268ee8..3cee8d5b85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java index 091dbb79c9..bec0c04b83 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslPredicateExecutorSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java index 8d5cdcb46c..23b0abdaee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java index aac577e3de..9969859076 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java index cc646d9aeb..f694100ef0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java index d253c86420..1da48bfc8e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -73,7 +73,7 @@ public ReactiveQuerydslMongoPredicateExecutor(MongoEntityInformation entit this.mongoOperations = mongoOperations; } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#findOne(com.querydsl.core.types.Predicate) */ @@ -85,7 +85,7 @@ public Mono findOne(Predicate predicate) { return createQueryFor(predicate).fetchOne(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#findAll(com.querydsl.core.types.Predicate) */ @@ -97,7 +97,7 @@ public Flux findAll(Predicate predicate) { return createQueryFor(predicate).fetch(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#findAll(com.querydsl.core.types.Predicate, com.querydsl.core.types.OrderSpecifier[]) */ @@ -110,7 +110,7 @@ public Flux findAll(Predicate predicate, OrderSpecifier... orders) { return createQueryFor(predicate).orderBy(orders).fetch(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#findAll(com.querydsl.core.types.Predicate, org.springframework.data.domain.Sort) */ @@ -123,7 +123,7 @@ public Flux findAll(Predicate predicate, Sort sort) { return applySorting(createQueryFor(predicate), sort).fetch(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#findAll(com.querydsl.core.types.OrderSpecifier[]) */ @@ -135,7 +135,7 @@ public Flux findAll(OrderSpecifier... orders) { return createQuery().orderBy(orders).fetch(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#count(com.querydsl.core.types.Predicate) */ @@ -147,7 +147,7 @@ public Mono count(Predicate predicate) { return createQueryFor(predicate).fetchCount(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor#exists(com.querydsl.core.types.Predicate) */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java index 9d598be37a..4162a79482 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index 3c26dbc8d1..73c8620820 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 the original author or authors. + * Copyright 2010-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 2390b5959d..11ba006cb3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java index 43c9f2339a..8a153d0c2c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java index e81b072b8d..e18f30d96a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 the original author or authors. + * Copyright 2011-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index c2dcec68bd..5b036072bf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java index 7edd8f2128..13412ba3b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/DBObjectUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java index 0511673fd2..a7077e9a31 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoClientVersion.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java index 042060c321..b2a299c4d0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/MongoDbErrorCodes.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java index e02c2d3640..48e2d9fdaf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/DateTimeFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java index e074411238..096c50cf4a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java index b49403ee62..42ac754cd2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonScanner.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java index 3e9fd396b1..6af33955cf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonToken.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java index 64c32360cc..fe8d2c7744 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/JsonTokenType.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java index 73900d456f..e5ee6f7492 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java index 900b41e7fd..18c9c25283 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingDocumentCodec.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index e0e1a61edd..17f8915df1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 the original author or authors. + * Copyright 2008-2021 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. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java index c99e0bc138..5110006316 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ValueProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt index 2fd80c780d..fdccda315f 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt index fdda7036eb..414ab0d4cd 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt index e4d9e661ea..aff46c4e15 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt index 62bf4bd21b..6d4fbb80d9 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableMapReduceOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt index 306ccde4a7..ebe0e4c793 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt index 4b41d4fb46..8e114f192f 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableUpdateOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt index 0044210ea8..6653cd67a3 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt index ac4eb370f9..89982f9bd6 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveAggregationOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt index 40bbc62b40..20f7398a03 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveChangeStreamOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt index 7dd69438ba..bbc4f36a65 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt index 06a15e494f..ca9147e2b0 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveInsertOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt index bb58c356b3..e9b27cde15 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMapReduceOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt index 714e22d5a7..f865cd43cc 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt index f0812542df..1b46f72740 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveRemoveOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt index de1a94c50e..d15a3567fb 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveUpdateOperationExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt index f7c52c8d4e..8d13ad7d35 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/CriteriaExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt index d88eae4e0a..4471e04a73 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPath.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt index 10a23bce6d..411d3697ea 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/KPropertyPathExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt index 92b784ea7b..b8762ffbe1 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2021 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. diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-2.2.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-2.2.xsd index bc1c52091a..775c6064b6 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-2.2.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-2.2.xsd @@ -1,6 +1,6 @@ From 48ac7e75ba585f05d7af992faf555f82449d250f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 3 May 2021 14:09:12 +0200 Subject: [PATCH 0425/1381] First pass of review polishing. Original pull request: #3647. Closes #3602. --- .../data/mongodb/core/convert/ReferenceLoader.java | 4 ++++ .../data/mongodb/core/convert/ReferenceReader.java | 5 ++++- .../data/mongodb/core/convert/ReferenceResolver.java | 1 + .../data/mongodb/core/mapping/ObjectReference.java | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java index 0bfd30d9b8..184918529e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java @@ -35,8 +35,10 @@ default Document fetch(ReferenceFilter filter, ReferenceContext context) { return bulkFetch(filter, context).findFirst().orElse(null); } + // meh, Stream! Stream bulkFetch(ReferenceFilter filter, ReferenceContext context); + // Reference query interface ReferenceFilter { Bson getFilter(); @@ -45,6 +47,8 @@ default Bson getSort() { return new Document(); } + // TODO: Move apply method into something else that holds the collection and knows about single item/multi-item + // processing default Stream apply(MongoCollection collection) { return restoreOrder(StreamSupport.stream(collection.find(getFilter()).sort(getSort()).spliterator(), false)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java index 84dfb9c38f..e5a16ea431 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java @@ -80,6 +80,7 @@ public ReferenceReader( this.codec = new ParameterBindingDocumentCodec(); } + // TODO: Move documentConversionFunction to here. Having a contextual read allows projections in references Object readReference(MongoPersistentProperty property, Object value, BiFunction> lookupFunction) { @@ -94,6 +95,8 @@ Object readReference(MongoPersistentProperty property, Object value, return result.map(it -> documentConversionFunction.apply(property, it)).collect(Collectors.toList()); } + // TODO: retain target type and extract types here so the conversion function doesn't require type fiddling + // BiFunction instead of MongoPersistentProperty if (property.isMap()) { // the order is a real problem here @@ -165,7 +168,7 @@ private T parseValueOrGet(String value, ParameterBindingContext bindingConte if (!BsonUtils.isJsonDocument(value) && value.contains("?#{")) { String s = "{ 'target-value' : " + value + "}"; - T evaluated = (T) new ParameterBindingDocumentCodec().decode(s, bindingContext).get("target-value "); + T evaluated = (T) codec.decode(s, bindingContext).get("target-value "); return evaluated != null ? evaluated : defaultValue.get(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java index ff08953633..50bc6558d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java @@ -47,6 +47,7 @@ default Object resolveReference(MongoPersistentProperty property, Object source, ReferenceLoader getReferenceLoader(); + // TODO: ReferenceCollection class ReferenceContext { @Nullable final String database; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java index ed787f66b4..9904b20d3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java @@ -19,6 +19,7 @@ * @author Christoph Strobl */ @FunctionalInterface +// TODO: ObjectPointer or DocumentPointer public interface ObjectReference { T getPointer(); } From 6ed274bd9bbff846546ebac412cea6be73a2e911 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 5 May 2021 09:44:53 +0200 Subject: [PATCH 0426/1381] Update entity linking support to derive document pointer from lookup query. Simplify usage by computing the pointer from the lookup. Update the reference documentation, add JavaDoc and refine API. Original pull request: #3647. Closes #3602. --- .../core/convert/DefaultDbRefResolver.java | 15 +- .../core/convert/DefaultReferenceLoader.java | 14 +- .../convert/DefaultReferenceResolver.java | 22 +- .../core/convert/DocumentPointerFactory.java | 135 +++++ .../core/convert/LazyLoadingProxy.java | 11 + .../convert/LazyLoadingProxyGenerator.java | 30 +- .../core/convert/MappingMongoConverter.java | 108 +++- .../mongodb/core/convert/MongoWriter.java | 4 + .../core/convert/NoOpDbRefResolver.java | 7 +- .../mongodb/core/convert/QueryMapper.java | 12 +- .../mongodb/core/convert/ReferenceLoader.java | 38 +- .../mongodb/core/convert/ReferenceReader.java | 136 ++--- .../core/convert/ReferenceResolver.java | 45 +- .../mapping/BasicMongoPersistentProperty.java | 19 + ...ectReference.java => DocumentPointer.java} | 13 +- .../core/mapping/DocumentReference.java | 86 ++- .../core/mapping/MongoPersistentProperty.java | 19 + .../UnwrappedMongoPersistentProperty.java | 11 + .../MongoTemplateDocumentReferenceTests.java | 548 ++++++++++++++++-- .../DefaultDbRefResolverUnitTests.java | 7 +- .../core/convert/QueryMapperUnitTests.java | 29 + .../performance/ReactivePerformanceTests.java | 7 +- ...tractPersonRepositoryIntegrationTests.java | 15 + .../data/mongodb/repository/Person.java | 12 + .../mongodb/repository/PersonRepository.java | 2 + src/main/asciidoc/new-features.adoc | 5 + src/main/asciidoc/reference/mapping.adoc | 365 ++++++++++++ 27 files changed, 1468 insertions(+), 247 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java rename spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/{ObjectReference.java => DocumentPointer.java} (57%) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 96b6c6876b..5277fbc0b0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -46,7 +46,7 @@ import org.springframework.data.mongodb.LazyLoadingException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoDatabaseUtils; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; +import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisStd; @@ -117,7 +117,8 @@ public Object resolveDbRef(MongoPersistentProperty property, @Nullable DBRef dbr */ @Override public Document fetch(DBRef dbRef) { - return getReferenceLoader().fetch(ReferenceFilter.singleReferenceFilter(Filters.eq("_id", dbRef.getId())), ReferenceContext.fromDBRef(dbRef)); + return getReferenceLoader().fetch(DocumentReferenceQuery.singleReferenceFilter(Filters.eq("_id", dbRef.getId())), + ReferenceCollection.fromDBRef(dbRef)); } /* @@ -157,9 +158,9 @@ public List bulkFetch(List refs) { databaseSource.getCollectionName()); } - List result = getReferenceLoader() - .bulkFetch(ReferenceFilter.referenceFilter(new Document("_id", new Document("$in", ids))), ReferenceContext.fromDBRef(refs.iterator().next())) - .collect(Collectors.toList()); + List result = mongoCollection // + .find(new Document("_id", new Document("$in", ids))) // + .into(new ArrayList<>()); return ids.stream() // .flatMap(id -> documentWithId(id, result)) // @@ -498,9 +499,9 @@ protected MongoCollection getCollection(DBRef dbref) { .getCollection(dbref.getCollectionName(), Document.class); } - protected MongoCollection getCollection(ReferenceContext context) { + protected MongoCollection getCollection(ReferenceCollection context) { - return MongoDatabaseUtils.getDatabase(context.database, mongoDbFactory).getCollection(context.collection, + return MongoDatabaseUtils.getDatabase(context.getDatabase(), mongoDbFactory).getCollection(context.getCollection(), Document.class); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java index 27feca163d..66b698077b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java @@ -15,21 +15,15 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - import org.bson.Document; -import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoDatabaseUtils; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceContext; -import org.springframework.lang.Nullable; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceCollection; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; /** @@ -49,7 +43,7 @@ public DefaultReferenceLoader(MongoDatabaseFactory mongoDbFactory) { } @Override - public Stream bulkFetch(ReferenceFilter filter, ReferenceContext context) { + public Iterable bulkFetch(DocumentReferenceQuery filter, ReferenceCollection context) { MongoCollection collection = getCollection(context); @@ -63,9 +57,9 @@ public Stream bulkFetch(ReferenceFilter filter, ReferenceContext conte return filter.apply(collection); } - protected MongoCollection getCollection(ReferenceContext context) { + protected MongoCollection getCollection(ReferenceCollection context) { - return MongoDatabaseUtils.getDatabase(context.database, mongoDbFactory).getCollection(context.collection, + return MongoDatabaseUtils.getDatabase(context.getDatabase(), mongoDbFactory).getCollection(context.getCollection(), Document.class); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java index b4324b505f..0692f719b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java @@ -15,12 +15,6 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.function.BiFunction; -import java.util.stream.Stream; - -import org.bson.Document; -import org.bson.conversions.Bson; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; @@ -44,24 +38,26 @@ public ReferenceLoader getReferenceLoader() { @Nullable @Override public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - BiFunction> lookupFunction) { + LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction) { if (isLazyReference(property)) { - return createLazyLoadingProxy(property, source, referenceReader, lookupFunction); + return createLazyLoadingProxy(property, source, referenceReader, lookupFunction, resultConversionFunction); } - return referenceReader.readReference(property, source, lookupFunction); + return referenceReader.readReference(property, source, lookupFunction, resultConversionFunction); } private Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, - ReferenceReader referenceReader, BiFunction> lookupFunction) { - return new LazyLoadingProxyGenerator(referenceReader).createLazyLoadingProxy(property, source, lookupFunction); + ReferenceReader referenceReader, LookupFunction lookupFunction, + ResultConversionFunction resultConversionFunction) { + return new LazyLoadingProxyGenerator(referenceReader).createLazyLoadingProxy(property, source, lookupFunction, + resultConversionFunction); } protected boolean isLazyReference(MongoPersistentProperty property) { - if (property.findAnnotation(DocumentReference.class) != null) { - return property.findAnnotation(DocumentReference.class).lazy(); + if (property.isDocumentReference()) { + return property.getDocumentReference().lazy(); } return property.getDBRef() != null && property.getDBRef().lazy(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java new file mode 100644 index 0000000000..a91a48d922 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java @@ -0,0 +1,135 @@ +/* + * Copyright 2021 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 + * + * https://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.convert; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.bson.Document; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.mapping.PersistentPropertyAccessor; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.model.BeanWrapperPropertyAccessorFactory; +import org.springframework.data.mongodb.core.mapping.DocumentPointer; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; + +/** + * @author Christoph Strobl + * @since 3.3 + */ +class DocumentPointerFactory { + + private ConversionService conversionService; + private MappingContext, MongoPersistentProperty> mappingContext; + private Map linkageMap; + + public DocumentPointerFactory(ConversionService conversionService, + MappingContext, MongoPersistentProperty> mappingContext) { + + this.conversionService = conversionService; + this.mappingContext = mappingContext; + this.linkageMap = new HashMap<>(); + } + + public DocumentPointer computePointer(MongoPersistentProperty property, Object value, Class typeHint) { + + if (value instanceof LazyLoadingProxy) { + return () -> ((LazyLoadingProxy) value).getSource(); + } + + if (conversionService.canConvert(typeHint, DocumentPointer.class)) { + return conversionService.convert(value, DocumentPointer.class); + } else { + + MongoPersistentEntity persistentEntity = mappingContext + .getPersistentEntity(property.getAssociationTargetType()); + + if (!property.getDocumentReference().lookup().toLowerCase().replaceAll("\\s", "").replaceAll("'", "") + .equals("{_id:?#{#target}}")) { + + return () -> linkageMap.computeIfAbsent(property.getDocumentReference().lookup(), key -> { + return new LinkageDocument(key); + }).get(persistentEntity, + BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(property.getOwner(), value)); + } + + // just take the id as a reference + return () -> persistentEntity.getIdentifierAccessor(value).getIdentifier(); + } + } + + static class LinkageDocument { + + String lookup; + org.bson.Document fetchDocument; + Map mapMap; + + public LinkageDocument(String lookup) { + + this.lookup = lookup; + String targetLookup = lookup; + + Pattern pattern = Pattern.compile("\\?#\\{#?[\\w\\d]*\\}"); + + Matcher matcher = pattern.matcher(lookup); + int index = 0; + mapMap = new LinkedHashMap<>(); + while (matcher.find()) { + + String expr = matcher.group(); + mapMap.put(Integer.valueOf(index), expr.substring(0, expr.length() - 1).replace("?#{#", "").replace("?#{", "") + .replace("target.", "").replaceAll("'", "")); + targetLookup = targetLookup.replace(expr, index + ""); + index++; + } + + fetchDocument = org.bson.Document.parse(targetLookup); + } + + org.bson.Document get(MongoPersistentEntity persistentEntity, PersistentPropertyAccessor propertyAccessor) { + + org.bson.Document targetDocument = new Document(); + + // TODO: recursive matching over nested Documents or would the parameter binding json parser be a thing? + // like we have it ordered by index values and could provide the parameter array from it. + + for (Entry entry : fetchDocument.entrySet()) { + + if (entry.getKey().equals("target")) { + + String refKey = mapMap.get(entry.getValue()); + + if (persistentEntity.hasIdProperty()) { + targetDocument.put(refKey, propertyAccessor.getProperty(persistentEntity.getIdProperty())); + } else { + targetDocument.put(refKey, propertyAccessor.getBean()); + } + continue; + } + + Object target = propertyAccessor.getProperty(persistentEntity.getPersistentProperty(entry.getKey())); + String refKey = mapMap.get(entry.getValue()); + targetDocument.put(refKey, target); + } + return targetDocument; + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java index a04a100cc5..8be7111988 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java @@ -46,4 +46,15 @@ public interface LazyLoadingProxy { */ @Nullable DBRef toDBRef(); + + /** + * Returns the raw {@literal source} object that defines the reference. + * + * @return can be {@literal null}. + * @since 3.3 + */ + @Nullable + default Object getSource() { + return toDBRef(); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java index 35da1e1e23..570a516d9b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java @@ -19,23 +19,19 @@ import java.io.Serializable; import java.lang.reflect.Method; -import java.util.function.BiFunction; -import java.util.stream.Stream; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -import org.bson.Document; -import org.bson.conversions.Bson; import org.springframework.aop.framework.ProxyFactory; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodProxy; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceContext; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.LookupFunction; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.ResultConversionFunction; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.objenesis.ObjenesisStd; import org.springframework.util.ReflectionUtils; @@ -54,11 +50,12 @@ public LazyLoadingProxyGenerator(ReferenceReader referenceReader) { this.objenesis = new ObjenesisStd(true); } - public Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, - BiFunction> lookupFunction) { + public Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, LookupFunction lookupFunction, + ResultConversionFunction resultConversionFunction) { Class propertyType = property.getType(); - LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, source, referenceReader, lookupFunction); + LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, source, referenceReader, lookupFunction, + resultConversionFunction); if (!propertyType.isInterface()) { @@ -105,27 +102,30 @@ public static class LazyLoadingInterceptor private volatile boolean resolved; private @org.springframework.lang.Nullable Object result; private Object source; - private BiFunction> lookupFunction; + private LookupFunction lookupFunction; + private ResultConversionFunction resultConversionFunction; - private final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD; + private final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD, GET_SOURCE_METHOD; { try { INITIALIZE_METHOD = LazyLoadingProxy.class.getMethod("getTarget"); TO_DBREF_METHOD = LazyLoadingProxy.class.getMethod("toDBRef"); FINALIZE_METHOD = Object.class.getDeclaredMethod("finalize"); + GET_SOURCE_METHOD = LazyLoadingProxy.class.getMethod("getSource"); } catch (Exception e) { throw new RuntimeException(e); } } public LazyLoadingInterceptor(MongoPersistentProperty property, Object source, ReferenceReader reader, - BiFunction> lookupFunction) { + LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction) { this.property = property; this.source = source; this.referenceReader = reader; this.lookupFunction = lookupFunction; + this.resultConversionFunction = resultConversionFunction; } @Nullable @@ -145,6 +145,10 @@ public Object intercept(Object o, Method method, Object[] args, MethodProxy prox return null; } + if (GET_SOURCE_METHOD.equals(method)) { + return source; + } + if (isObjectMethod(method) && Object.class.equals(method.getDeclaringClass())) { if (ReflectionUtils.isToStringMethod(method)) { @@ -234,7 +238,7 @@ private synchronized Object resolve() { // property.getOwner() != null ? property.getOwner().getName() : "unknown", property.getName()); // } - return referenceReader.readReference(property, source, lookupFunction); + return referenceReader.readReference(property, source, lookupFunction, resultConversionFunction); } catch (RuntimeException ex) { throw ex; 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 0d3378d39f..2ad4d75230 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 @@ -63,10 +63,9 @@ import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider; import org.springframework.data.mongodb.CodecRegistryProvider; import org.springframework.data.mongodb.MongoDatabaseFactory; -import org.springframework.data.mongodb.core.mapping.DocumentReference; +import org.springframework.data.mongodb.core.mapping.DocumentPointer; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; -import org.springframework.data.mongodb.core.mapping.ObjectReference; import org.springframework.data.mongodb.core.mapping.Unwrapped; import org.springframework.data.mongodb.core.mapping.Unwrapped.OnEmpty; import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback; @@ -124,6 +123,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App private SpELContext spELContext; private @Nullable EntityCallbacks entityCallbacks; + private DocumentPointerFactory documentPointerFactory; /** * Creates a new {@link MappingMongoConverter} given the new {@link DbRefResolver} and {@link MappingContext}. @@ -154,8 +154,8 @@ public MappingMongoConverter(DbRefResolver dbRefResolver, return MappingMongoConverter.this.getValueInternal(context, prop, bson, evaluator); }); - this.referenceReader = new ReferenceReader(mappingContext, - (prop, document) -> this.read(prop.getActualType(), document), () -> spELContext); + this.referenceReader = new ReferenceReader(mappingContext, () -> spELContext); + this.documentPointerFactory = new DocumentPointerFactory(conversionService, mappingContext); } /** @@ -366,6 +366,14 @@ private S read(ConversionContext context, MongoPersistentEnti SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext); DocumentAccessor documentAccessor = new DocumentAccessor(bson); + if (bson.get("_id") != null) { + + Object existing = context.getPath().getPathItem(bson.get("_id"), entity.getCollection(), entity.getType()); + if (existing != null) { + return (S) existing; + } + } + PreferredConstructor persistenceConstructor = entity.getPersistenceConstructor(); ParameterValueProvider provider = persistenceConstructor != null @@ -376,6 +384,7 @@ private S read(ConversionContext context, MongoPersistentEnti S instance = instantiator.createInstance(entity, provider); if (entity.requiresPropertyPopulation()) { + return populateProperties(context, entity, documentAccessor, evaluator, instance); } @@ -451,7 +460,8 @@ private void readProperties(ConversionContext context, MongoPersistentEntity callback = getDbRefResolverCallback(context, documentAccessor, evaluator); } - readAssociation(prop.getRequiredAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback); + readAssociation(prop.getRequiredAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback, context, + evaluator); continue; } @@ -478,7 +488,8 @@ private void readProperties(ConversionContext context, MongoPersistentEntity callback = getDbRefResolverCallback(context, documentAccessor, evaluator); } - readAssociation(prop.getRequiredAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback); + readAssociation(prop.getRequiredAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback, context, + evaluator); continue; } @@ -494,7 +505,8 @@ private DbRefResolverCallback getDbRefResolverCallback(ConversionContext context } private void readAssociation(Association association, PersistentPropertyAccessor accessor, - DocumentAccessor documentAccessor, DbRefProxyHandler handler, DbRefResolverCallback callback) { + DocumentAccessor documentAccessor, DbRefProxyHandler handler, DbRefResolverCallback callback, + ConversionContext context, SpELExpressionEvaluator evaluator) { MongoPersistentProperty property = association.getInverse(); final Object value = documentAccessor.get(property); @@ -503,26 +515,32 @@ private void readAssociation(Association association, P return; } - if (property.isAnnotationPresent(DocumentReference.class)) { + if (property.isDocumentReference()) { // quite unusual but sounds like worth having? - if (conversionService.canConvert(ObjectReference.class, property.getActualType())) { + if (conversionService.canConvert(DocumentPointer.class, property.getActualType())) { - // collection like special treatment - accessor.setProperty(property, conversionService.convert(new ObjectReference() { + DocumentPointer pointer = new DocumentPointer() { @Override public Object getPointer() { return value; } - }, property.getActualType())); + }; + + // collection like special treatment + accessor.setProperty(property, conversionService.convert(pointer, property.getActualType())); } else { - accessor.setProperty(property, dbRefResolver.resolveReference(property, value, referenceReader)); + accessor.setProperty(property, + dbRefResolver.resolveReference(property, value, referenceReader, context::convert)); } return; } DBRef dbref = value instanceof DBRef ? (DBRef) value : null; + + // TODO: accessor.setProperty(property, dbRefResolver.resolveReference(property, value, referenceReader, + // context::convert)); accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler)); } @@ -563,6 +581,45 @@ public DBRef toDBRef(Object object, @Nullable MongoPersistentProperty referringP return createDBRef(object, referringProperty); } + public Object toDocumentReference(Object source, @Nullable MongoPersistentProperty referringProperty) { + + if (source instanceof LazyLoadingProxy) { + return ((LazyLoadingProxy) source).getSource(); + } + + if (referringProperty != null) { + + if (referringProperty.isDbReference()) { + return toDBRef(source, referringProperty); + } + if (referringProperty.isDocumentReference()) { + return createDocumentPointer(source, referringProperty); + } + } + + throw new RuntimeException("oops - what's that " + source); + } + + Object createDocumentPointer(Object source, @Nullable MongoPersistentProperty referringProperty) { + + if (referringProperty == null) { + return source; + } + + if (ClassUtils.isAssignableValue(referringProperty.getType(), source) + && conversionService.canConvert(referringProperty.getType(), DocumentPointer.class)) { + return conversionService.convert(source, DocumentPointer.class).getPointer(); + } + + if (ClassUtils.isAssignableValue(referringProperty.getAssociationTargetType(), source)) { + return documentPointerFactory.computePointer(referringProperty, source, referringProperty.getActualType()) + .getPointer(); + + } + + return source; + } + /** * Root entry method into write conversion. Adds a type discriminator to the {@link Document}. Shouldn't be called for * nested conversions. @@ -749,13 +806,8 @@ protected void writePropertyInternal(@Nullable Object obj, DocumentAccessor acce if (prop.isAssociation()) { - if (conversionService.canConvert(valueType.getType(), ObjectReference.class)) { - accessor.put(prop, conversionService.convert(obj, ObjectReference.class).getPointer()); - } else { - // just take the id as a reference - accessor.put(prop, mappingContext.getPersistentEntity(prop.getAssociationTargetType()) - .getIdentifierAccessor(obj).getIdentifier()); - } + accessor.put(prop, new DocumentPointerFactory(conversionService, mappingContext) + .computePointer(prop, obj, valueType.getType()).getPointer()); return; } @@ -799,14 +851,14 @@ protected List createCollection(Collection collection, MongoPersisten if (property.isAssociation()) { return writeCollectionInternal(collection.stream().map(it -> { - if (conversionService.canConvert(it.getClass(), ObjectReference.class)) { - return conversionService.convert(it, ObjectReference.class).getPointer(); + if (conversionService.canConvert(it.getClass(), DocumentPointer.class)) { + return conversionService.convert(it, DocumentPointer.class).getPointer(); } else { // just take the id as a reference return mappingContext.getPersistentEntity(property.getAssociationTargetType()).getIdentifierAccessor(it) .getIdentifier(); } - }).collect(Collectors.toList()), ClassTypeInformation.from(ObjectReference.class), new BasicDBList()); + }).collect(Collectors.toList()), ClassTypeInformation.from(DocumentPointer.class), new BasicDBList()); } if (property.hasExplicitWriteTarget()) { @@ -855,15 +907,15 @@ protected Bson createMap(Map map, MongoPersistentProperty proper if (conversions.isSimpleType(key.getClass())) { String simpleKey = prepareMapKey(key.toString()); - if(property.isDbReference()) { + if (property.isDbReference()) { document.put(simpleKey, value != null ? createDBRef(value, property) : null); } else { - if (conversionService.canConvert(value.getClass(), ObjectReference.class)) { - document.put(simpleKey, conversionService.convert(value, ObjectReference.class).getPointer()); + if (conversionService.canConvert(value.getClass(), DocumentPointer.class)) { + document.put(simpleKey, conversionService.convert(value, DocumentPointer.class).getPointer()); } else { // just take the id as a reference - document.put(simpleKey, mappingContext.getPersistentEntity(property.getAssociationTargetType()).getIdentifierAccessor(value) - .getIdentifier()); + document.put(simpleKey, mappingContext.getPersistentEntity(property.getAssociationTargetType()) + .getIdentifierAccessor(value).getIdentifier()); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java index 0f64177bca..779b3236d3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java @@ -70,4 +70,8 @@ default Object convertToMongoType(@Nullable Object obj, MongoPersistentEntity * @return will never be {@literal null}. */ DBRef toDBRef(Object object, @Nullable MongoPersistentProperty referingProperty); + + default Object toDocumentReference(Object source, @Nullable MongoPersistentProperty referringProperty) { + return toDBRef(source, referringProperty); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java index cbd02ee74d..8b6c969439 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java @@ -20,9 +20,9 @@ import java.util.stream.Stream; import org.bson.Document; -import org.bson.conversions.Bson; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; +import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import com.mongodb.DBRef; @@ -77,7 +77,8 @@ private T handle() throws UnsupportedOperationException { @Nullable @Override public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - BiFunction> lookupFunction) { + LookupFunction lookupFunction, + ResultConversionFunction resultConversionFunction) { return null; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index af93fdd634..36353e4f86 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -605,7 +605,7 @@ protected Object convertAssociation(@Nullable Object source, @Nullable MongoPers if (source instanceof Iterable) { BasicDBList result = new BasicDBList(); for (Object element : (Iterable) source) { - result.add(createDbRefFor(element, property)); + result.add(createReferenceFor(element, property)); } return result; } @@ -614,12 +614,12 @@ protected Object convertAssociation(@Nullable Object source, @Nullable MongoPers Document result = new Document(); Document dbObject = (Document) source; for (String key : dbObject.keySet()) { - result.put(key, createDbRefFor(dbObject.get(key), property)); + result.put(key, createReferenceFor(dbObject.get(key), property)); } return result; } - return createDbRefFor(source, property); + return createReferenceFor(source, property); } /** @@ -666,12 +666,16 @@ private Entry createMapEntry(String key, @Nullable Object value) return Collections.singletonMap(key, value).entrySet().iterator().next(); } - private DBRef createDbRefFor(Object source, MongoPersistentProperty property) { + private Object createReferenceFor(Object source, MongoPersistentProperty property) { if (source instanceof DBRef) { return (DBRef) source; } + if(property != null && property.isDocumentReference()) { + return converter.toDocumentReference(source, property); + } + return converter.toDBRef(source, property); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java index 184918529e..d5c72afad8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java @@ -15,12 +15,12 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; +import java.util.Collections; +import java.util.Iterator; import org.bson.Document; import org.bson.conversions.Bson; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceContext; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceCollection; import org.springframework.lang.Nullable; import com.mongodb.client.MongoCollection; @@ -31,15 +31,15 @@ public interface ReferenceLoader { @Nullable - default Document fetch(ReferenceFilter filter, ReferenceContext context) { - return bulkFetch(filter, context).findFirst().orElse(null); + default Document fetch(DocumentReferenceQuery filter, ReferenceCollection context) { + + Iterator it = bulkFetch(filter, context).iterator(); + return it.hasNext() ? it.next() : null; } - // meh, Stream! - Stream bulkFetch(ReferenceFilter filter, ReferenceContext context); + Iterable bulkFetch(DocumentReferenceQuery filter, ReferenceCollection context); - // Reference query - interface ReferenceFilter { + interface DocumentReferenceQuery { Bson getFilter(); @@ -49,21 +49,21 @@ default Bson getSort() { // TODO: Move apply method into something else that holds the collection and knows about single item/multi-item // processing - default Stream apply(MongoCollection collection) { - return restoreOrder(StreamSupport.stream(collection.find(getFilter()).sort(getSort()).spliterator(), false)); + default Iterable apply(MongoCollection collection) { + return restoreOrder(collection.find(getFilter()).sort(getSort())); } - - default Stream restoreOrder(Stream stream) { - return stream; + + default Iterable restoreOrder(Iterable documents) { + return documents; } - static ReferenceFilter referenceFilter(Bson bson) { + static DocumentReferenceQuery referenceFilter(Bson bson) { return () -> bson; } - static ReferenceFilter singleReferenceFilter(Bson bson) { + static DocumentReferenceQuery singleReferenceFilter(Bson bson) { - return new ReferenceFilter() { + return new DocumentReferenceQuery() { @Override public Bson getFilter() { @@ -71,10 +71,10 @@ public Bson getFilter() { } @Override - public Stream apply(MongoCollection collection) { + public Iterable apply(MongoCollection collection) { Document result = collection.find(getFilter()).sort(getSort()).limit(1).first(); - return result != null ? Stream.of(result) : Stream.empty(); + return result != null ? Collections.singleton(result) : Collections.emptyList(); } }; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java index e5a16ea431..fb37367b1d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java @@ -17,24 +17,24 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; -import java.util.function.BiFunction; import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.bson.Document; import org.bson.conversions.Bson; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.SpELContext; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceContext; +import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.LookupFunction; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceCollection; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.ResultConversionFunction; import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; @@ -56,61 +56,47 @@ */ public class ReferenceReader { - private final ParameterBindingDocumentCodec codec; - private final Lazy, MongoPersistentProperty>> mappingContext; - private final BiFunction documentConversionFunction; private final Supplier spelContextSupplier; + private final ParameterBindingDocumentCodec codec; public ReferenceReader(MappingContext, MongoPersistentProperty> mappingContext, - BiFunction documentConversionFunction, Supplier spelContextSupplier) { - this(() -> mappingContext, documentConversionFunction, spelContextSupplier); + this(() -> mappingContext, spelContextSupplier); } public ReferenceReader( Supplier, MongoPersistentProperty>> mappingContextSupplier, - BiFunction documentConversionFunction, Supplier spelContextSupplier) { this.mappingContext = Lazy.of(mappingContextSupplier); - this.documentConversionFunction = documentConversionFunction; this.spelContextSupplier = spelContextSupplier; this.codec = new ParameterBindingDocumentCodec(); } - // TODO: Move documentConversionFunction to here. Having a contextual read allows projections in references - Object readReference(MongoPersistentProperty property, Object value, - BiFunction> lookupFunction) { + Object readReference(MongoPersistentProperty property, Object value, LookupFunction lookupFunction, + ResultConversionFunction resultConversionFunction) { SpELContext spELContext = spelContextSupplier.get(); - ReferenceFilter filter = computeFilter(property, value, spELContext); - ReferenceContext referenceContext = computeReferenceContext(property, value, spELContext); + DocumentReferenceQuery filter = computeFilter(property, value, spELContext); + ReferenceCollection referenceCollection = computeReferenceContext(property, value, spELContext); - Stream result = lookupFunction.apply(referenceContext, filter); + Iterable result = lookupFunction.apply(filter, referenceCollection); - if (property.isCollectionLike()) { - return result.map(it -> documentConversionFunction.apply(property, it)).collect(Collectors.toList()); + if (!result.iterator().hasNext()) { + return null; } - // TODO: retain target type and extract types here so the conversion function doesn't require type fiddling - // BiFunction instead of MongoPersistentProperty - if (property.isMap()) { - - // the order is a real problem here - Iterator keyIterator = ((Map) value).keySet().iterator(); - return result.map(it -> it.entrySet().stream().collect(Collectors.toMap(key -> key.getKey(), val -> { - Object apply = documentConversionFunction.apply(property, (Document) val.getValue()); - return apply; - }))).findFirst().orElse(null); + if (property.isCollectionLike()) { + return resultConversionFunction.apply(result, property.getTypeInformation()); } - return result.map(it -> documentConversionFunction.apply(property, it)).findFirst().orElse(null); + return resultConversionFunction.apply(result.iterator().next(), property.getTypeInformation()); } - private ReferenceContext computeReferenceContext(MongoPersistentProperty property, Object value, + private ReferenceCollection computeReferenceContext(MongoPersistentProperty property, Object value, SpELContext spELContext) { if (value instanceof Iterable) { @@ -118,44 +104,43 @@ private ReferenceContext computeReferenceContext(MongoPersistentProperty propert } if (value instanceof DBRef) { - return ReferenceContext.fromDBRef((DBRef) value); + return ReferenceCollection.fromDBRef((DBRef) value); } if (value instanceof Document) { Document ref = (Document) value; - if (property.isAnnotationPresent(DocumentReference.class)) { + if (property.isDocumentReference()) { ParameterBindingContext bindingContext = bindingContext(property, value, spELContext); - DocumentReference documentReference = property.getRequiredAnnotation(DocumentReference.class); + DocumentReference documentReference = property.getDocumentReference(); String targetDatabase = parseValueOrGet(documentReference.db(), bindingContext, () -> ref.get("db", String.class)); String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, () -> ref.get("collection", mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection())); - return new ReferenceContext(targetDatabase, targetCollection); + return new ReferenceCollection(targetDatabase, targetCollection); } - return new ReferenceContext(ref.getString("db"), ref.get("collection", + return new ReferenceCollection(ref.getString("db"), ref.get("collection", mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection())); } - if (property.isAnnotationPresent(DocumentReference.class)) { + if (property.isDocumentReference()) { ParameterBindingContext bindingContext = bindingContext(property, value, spELContext); - DocumentReference documentReference = property.getRequiredAnnotation(DocumentReference.class); + DocumentReference documentReference = property.getDocumentReference(); String targetDatabase = parseValueOrGet(documentReference.db(), bindingContext, () -> null); String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, () -> mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection()); - Document sort = parseValueOrGet(documentReference.sort(), bindingContext, () -> null); - return new ReferenceContext(targetDatabase, targetCollection); + return new ReferenceCollection(targetDatabase, targetCollection); } - return new ReferenceContext(null, + return new ReferenceCollection(null, mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection()); } @@ -201,9 +186,9 @@ EvaluationContext evaluationContextFor(MongoPersistentProperty property, Object return ctx; } - ReferenceFilter computeFilter(MongoPersistentProperty property, Object value, SpELContext spELContext) { + DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object value, SpELContext spELContext) { - DocumentReference documentReference = property.getRequiredAnnotation(DocumentReference.class); + DocumentReference documentReference = property.getDocumentReference(); String lookup = documentReference.lookup(); Document sort = parseValueOrGet(documentReference.sort(), bindingContext(property, value, spELContext), () -> null); @@ -217,7 +202,7 @@ ReferenceFilter computeFilter(MongoPersistentProperty property, Object value, Sp ors.add(decoded); } - return new ListReferenceFilter(new Document("$or", ors), sort); + return new ListDocumentReferenceQuery(new Document("$or", ors), sort); } if (property.isMap() && value instanceof Map) { @@ -230,18 +215,18 @@ ReferenceFilter computeFilter(MongoPersistentProperty property, Object value, Sp filterMap.put(entry.getKey(), decoded); } - return new MapReferenceFilter(new Document("$or", filterMap.values()), sort, filterMap); + return new MapDocumentReferenceQuery(new Document("$or", filterMap.values()), sort, filterMap); } - return new SingleReferenceFilter(codec.decode(lookup, bindingContext(property, value, spELContext)), sort); + return new SingleDocumentReferenceQuery(codec.decode(lookup, bindingContext(property, value, spELContext)), sort); } - static class SingleReferenceFilter implements ReferenceFilter { + static class SingleDocumentReferenceQuery implements DocumentReferenceQuery { Document filter; Document sort; - public SingleReferenceFilter(Document filter, Document sort) { + public SingleDocumentReferenceQuery(Document filter, Document sort) { this.filter = filter; this.sort = sort; } @@ -252,24 +237,24 @@ public Bson getFilter() { } @Override - public Stream apply(MongoCollection collection) { + public Iterable apply(MongoCollection collection) { Document result = collection.find(getFilter()).limit(1).first(); - return result != null ? Stream.of(result) : Stream.empty(); + return result != null ? Collections.singleton(result) : Collections.emptyList(); } } - static class MapReferenceFilter implements ReferenceFilter { + static class MapDocumentReferenceQuery implements DocumentReferenceQuery { - Document filter; - Document sort; - Map filterOrderMap; + private final Document filter; + private final Document sort; + private final Map filterOrderMap; - public MapReferenceFilter(Document filter, Document sort, Map filterOrderMap) { + public MapDocumentReferenceQuery(Document filter, Document sort, Map filterOrderMap) { this.filter = filter; - this.filterOrderMap = filterOrderMap; this.sort = sort; + this.filterOrderMap = filterOrderMap; } @Override @@ -283,45 +268,46 @@ public Bson getSort() { } @Override - public Stream restoreOrder(Stream stream) { + public Iterable restoreOrder(Iterable documents) { Map targetMap = new LinkedHashMap<>(); - List collected = stream.collect(Collectors.toList()); + List collected = documents instanceof List ? (List) documents + : Streamable.of(documents).toList(); for (Entry filterMapping : filterOrderMap.entrySet()) { - String key = filterMapping.getKey().toString(); - Optional first = collected.stream().filter(it -> { + Optional first = collected.stream() + .filter(it -> it.entrySet().containsAll(filterMapping.getValue().entrySet())).findFirst(); - boolean found = it.entrySet().containsAll(filterMapping.getValue().entrySet()); - return found; - }).findFirst(); - - targetMap.put(key, first.orElse(null)); + targetMap.put(filterMapping.getKey().toString(), first.orElse(null)); } - return Stream.of(new Document(targetMap)); + return Collections.singleton(new Document(targetMap)); } } - static class ListReferenceFilter implements ReferenceFilter { + static class ListDocumentReferenceQuery implements DocumentReferenceQuery { - Document filter; - Document sort; + private final Document filter; + private final Document sort; + + public ListDocumentReferenceQuery(Document filter, Document sort) { - public ListReferenceFilter(Document filter, Document sort) { this.filter = filter; this.sort = sort; } @Override - public Stream restoreOrder(Stream stream) { + public Iterable restoreOrder(Iterable documents) { if (filter.containsKey("$or")) { List ors = filter.get("$or", List.class); - return stream.sorted((o1, o2) -> compareAgainstReferenceIndex(ors, o1, o2)); + List target = documents instanceof List ? (List) documents + : Streamable.of(documents).toList(); + return target.stream().sorted((o1, o2) -> compareAgainstReferenceIndex(ors, o1, o2)) + .collect(Collectors.toList()); } - return stream; + return documents; } public Document getFilter() { @@ -347,7 +333,5 @@ int compareAgainstReferenceIndex(List referenceList, Document document } return referenceList.size(); } - } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java index 50bc6558d3..f29dc16a7c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java @@ -15,13 +15,12 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.function.BiFunction; -import java.util.stream.Stream; +import java.util.Collections; import org.bson.Document; -import org.bson.conversions.Bson; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; +import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import com.mongodb.DBRef; @@ -33,34 +32,38 @@ public interface ReferenceResolver { @Nullable Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - BiFunction> lookupFunction); + LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction); - default Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader) { - return resolveReference(property, source, referenceReader, (ctx, filter) -> { + default Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, + ResultConversionFunction resultConversionFunction) { + + return resolveReference(property, source, referenceReader, (filter, ctx) -> { if (property.isCollectionLike() || property.isMap()) { return getReferenceLoader().bulkFetch(filter, ctx); + } + Object target = getReferenceLoader().fetch(filter, ctx); - return target == null ? Stream.empty() : Stream.of(getReferenceLoader().fetch(filter, ctx)); - }); + return target == null ? Collections.emptyList() : Collections.singleton(getReferenceLoader().fetch(filter, ctx)); + }, resultConversionFunction); } ReferenceLoader getReferenceLoader(); - // TODO: ReferenceCollection - class ReferenceContext { + class ReferenceCollection { - @Nullable final String database; - final String collection; + @Nullable + private final String database; + private final String collection; - public ReferenceContext(@Nullable String database, String collection) { + public ReferenceCollection(@Nullable String database, String collection) { this.database = database; this.collection = collection; } - static ReferenceContext fromDBRef(DBRef dbRef) { - return new ReferenceContext(dbRef.getDatabaseName(), dbRef.getCollectionName()); + static ReferenceCollection fromDBRef(DBRef dbRef) { + return new ReferenceCollection(dbRef.getDatabaseName(), dbRef.getCollectionName()); } public String getCollection() { @@ -72,4 +75,14 @@ public String getDatabase() { return database; } } + + @FunctionalInterface + interface LookupFunction { + Iterable apply(DocumentReferenceQuery referenceQuery, ReferenceCollection referenceCollection); + } + + @FunctionalInterface + interface ResultConversionFunction { + Object apply(Object source, TypeInformation property); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 0b47c79d04..b7b71a7fee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -231,6 +231,15 @@ public boolean isDbReference() { return isAnnotationPresent(DBRef.class); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isDocumentReference() + */ + @Override + public boolean isDocumentReference() { + return isAnnotationPresent(DocumentReference.class); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDBRef() @@ -240,6 +249,16 @@ public DBRef getDBRef() { return findAnnotation(DBRef.class); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDocumentReference() + */ + @Nullable + @Override + public DocumentReference getDocumentReference() { + return findAnnotation(DocumentReference.class); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isLanguageProperty() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java similarity index 57% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java index 9904b20d3f..de7fbff866 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/ObjectReference.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java @@ -16,10 +16,19 @@ package org.springframework.data.mongodb.core.mapping; /** + * A custom pointer to a linked document to be used along with {@link DocumentReference} for storing the linkage value. + * * @author Christoph Strobl */ @FunctionalInterface -// TODO: ObjectPointer or DocumentPointer -public interface ObjectReference { +public interface DocumentPointer { + + /** + * The actual pointer value. This can be any simple type, like a {@link String} or {@link org.bson.types.ObjectId} or + * a {@link org.bson.Document} holding more information like the target collection, multiple fields forming the key, + * etc. + * + * @return the value stored in MongoDB and used for constructing the {@link DocumentReference#lookup() lookup query}. + */ T getPointer(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java index d9af6ccee1..0846c4022c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java @@ -24,8 +24,69 @@ import org.springframework.data.annotation.Reference; /** + * A {@link DocumentReference} offers an alternative way of linking entities in MongoDB. While the goal is the same as + * when using {@link DBRef}, the store representation is different and can be literally anything, a single value, an + * entire {@link org.bson.Document}, basically everything that can be stored in MongoDB. By default, the mapping layer + * will use the referenced entities {@literal id} value for storage and retrieval. + * + *
      + * public class Account {
      + *   private String id;
      + *   private Float total;
      + * }
      + *
      + * public class Person {
      + *   private String id;
      + *   @DocumentReference
      + *   private List<Account> accounts;
      + * }
      + * 
      + * Account account = ...
      + *
      + * mongoTemplate.insert(account);
      + *
      + * template.update(Person.class)
      + *   .matching(where("id").is(...))
      + *   .apply(new Update().push("accounts").value(account))
      + *   .first();
      + * 
      + * + * {@link #lookup()} allows to define custom queries that are independent from the {@literal id} field and in + * combination with {@link org.springframework.data.convert.WritingConverter writing converters} offer a flexible way of + * defining links between entities. + * + *
      + * public class Book {
      + * 	 private ObjectId id;
      + * 	 private String title;
      + *
      + * 	 @Field("publisher_ac")
      + * 	 @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }")
      + * 	 private Publisher publisher;
      + * }
      + *
      + * public class Publisher {
      + *
      + * 	 private ObjectId id;
      + * 	 private String acronym;
      + * 	 private String name;
      + *
      + * 	 @DocumentReference(lazy = true)
      + * 	 private List<Book> books;
      + * }
      + *
      + * @WritingConverter
      + * public class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> {
      + *
      + *    public DocumentPointer<String> convert(Publisher source) {
      + * 		return () -> source.getAcronym();
      + *    }
      + * }
      + * 
      + * * @author Christoph Strobl * @since 3.3 + * @see MongoDB Reference Documentation */ @Documented @Retention(RetentionPolicy.RUNTIME) @@ -34,17 +95,38 @@ public @interface DocumentReference { /** - * The database the referred entity resides in. + * The database the linked entity resides in. * - * @return empty String by default. + * @return empty String by default. Uses the default database provided buy the {@link org.springframework.data.mongodb.MongoDatabaseFactory}. */ String db() default ""; + /** + * The database the linked entity resides in. + * + * @return empty String by default. Uses the property type for collection resolution. + */ String collection() default ""; + /** + * The single document lookup query. In case of an {@link java.util.Collection} or {@link java.util.Map} property + * the individual lookups are combined via an `$or` operator. + * + * @return an {@literal _id} based lookup. + */ String lookup() default "{ '_id' : ?#{#target} }"; + /** + * A specific sort. + * + * @return empty String by default. + */ String sort() default ""; + /** + * Controls whether the referenced entity should be loaded lazily. This defaults to {@literal false}. + * + * @return {@literal false} by default. + */ boolean lazy() default false; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index 7c347229b6..c753f3856d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -62,6 +62,15 @@ public interface MongoPersistentProperty extends PersistentProperty { - it.customConverters(new ReferencableConverter()); + it.customConverters(new ReferencableConverter(), new SimpleObjectRefWithReadingConverterToDocumentConverter(), + new DocumentToSimpleObjectRefWithReadingConverter()); }); cfg.configureMappingContext(it -> { @@ -84,7 +87,7 @@ public void setUp() { template.flushDatabase(); } - @Test + @Test // GH-3602 void writeSimpleTypeReference() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -102,12 +105,11 @@ void writeSimpleTypeReference() { assertThat(target.get("simpleValueRef")).isEqualTo("ref-1"); } - @Test + @Test // GH-3602 void writeMapTypeReference() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); - CollectionRefRoot source = new CollectionRefRoot(); source.id = "root-1"; source.mapValueRef = new LinkedHashMap<>(); @@ -120,11 +122,10 @@ void writeMapTypeReference() { return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); }); - System.out.println("target: " + target.toJson()); assertThat(target.get("mapValueRef", Map.class)).containsEntry("frodo", "ref-1").containsEntry("bilbo", "ref-2"); } - @Test + @Test // GH-3602 void writeCollectionOfSimpleTypeReference() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -143,7 +144,7 @@ void writeCollectionOfSimpleTypeReference() { assertThat(target.get("simpleValueRef", List.class)).containsExactly("ref-1", "ref-2"); } - @Test + @Test // GH-3602 void writeObjectTypeReference() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -161,7 +162,7 @@ void writeObjectTypeReference() { assertThat(target.get("objectValueRef")).isEqualTo(source.getObjectValueRef().toReference()); } - @Test + @Test // GH-3602 void writeCollectionOfObjectTypeReference() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -181,7 +182,7 @@ void writeCollectionOfObjectTypeReference() { source.getObjectValueRef().get(0).toReference(), source.getObjectValueRef().get(1).toReference()); } - @Test + @Test // GH-3602 void readSimpleTypeObjectReference() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -200,7 +201,7 @@ void readSimpleTypeObjectReference() { assertThat(result.getSimpleValueRef()).isEqualTo(new SimpleObjectRef("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readCollectionOfSimpleTypeObjectReference() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -220,7 +221,7 @@ void readCollectionOfSimpleTypeObjectReference() { assertThat(result.getSimpleValueRef()).containsExactly(new SimpleObjectRef("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readLazySimpleTypeObjectReference() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -245,7 +246,7 @@ void readLazySimpleTypeObjectReference() { assertThat(result.getSimpleLazyValueRef()).isEqualTo(new SimpleObjectRef("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readSimpleTypeObjectReferenceFromFieldWithCustomName() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -266,7 +267,7 @@ void readSimpleTypeObjectReferenceFromFieldWithCustomName() { .isEqualTo(new SimpleObjectRef("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readCollectionTypeObjectReferenceFromFieldWithCustomName() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -287,7 +288,7 @@ void readCollectionTypeObjectReferenceFromFieldWithCustomName() { .containsExactly(new SimpleObjectRef("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readObjectReferenceFromDocumentType() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -307,7 +308,7 @@ void readObjectReferenceFromDocumentType() { assertThat(result.getObjectValueRef()).isEqualTo(new ObjectRefOfDocument("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readCollectionObjectReferenceFromDocumentType() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -328,7 +329,7 @@ void readCollectionObjectReferenceFromDocumentType() { .containsExactly(new ObjectRefOfDocument("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readObjectReferenceFromDocumentDeclaringCollectionName() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -351,7 +352,7 @@ void readObjectReferenceFromDocumentDeclaringCollectionName() { .isEqualTo(new ObjectRefOfDocumentWithEmbeddedCollectionName("ref-1", "me-the-referenced-object")); } - @Test + @Test // GH-3602 void readCollectionObjectReferenceFromDocumentDeclaringCollectionName() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -379,7 +380,7 @@ void readCollectionObjectReferenceFromDocumentDeclaringCollectionName() { new ObjectRefOfDocumentWithEmbeddedCollectionName("ref-1", "me-the-1-referenced-object")); } - @Test + @Test // GH-3602 void readObjectReferenceFromDocumentNotRelatingToTheIdProperty() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -401,7 +402,7 @@ void readObjectReferenceFromDocumentNotRelatingToTheIdProperty() { .isEqualTo(new ObjectRefOnNonIdField("ref-1", "me-the-referenced-object", "ref-key-1", "ref-key-2")); } - @Test + @Test // GH-3602 void readLazyObjectReferenceFromDocumentNotRelatingToTheIdProperty() { String rootCollectionName = template.getCollectionName(SingleRefRoot.class); @@ -429,7 +430,7 @@ void readLazyObjectReferenceFromDocumentNotRelatingToTheIdProperty() { .isEqualTo(new ObjectRefOnNonIdField("ref-1", "me-the-referenced-object", "ref-key-1", "ref-key-2")); } - @Test + @Test // GH-3602 void readCollectionObjectReferenceFromDocumentNotRelatingToTheIdProperty() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -452,7 +453,7 @@ void readCollectionObjectReferenceFromDocumentNotRelatingToTheIdProperty() { .containsExactly(new ObjectRefOnNonIdField("ref-1", "me-the-referenced-object", "ref-key-1", "ref-key-2")); } - @Test + @Test // GH-3602 void readMapOfReferences() { String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); @@ -479,12 +480,414 @@ void readMapOfReferences() { }); CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); - System.out.println("result: " + result); - assertThat(result.getMapValueRef()).containsEntry("frodo", - new SimpleObjectRef("ref-1", "me-the-1-referenced-object")) - .containsEntry("bilbo", - new SimpleObjectRef("ref-2", "me-the-2-referenced-object")); + assertThat(result.getMapValueRef()) + .containsEntry("frodo", new SimpleObjectRef("ref-1", "me-the-1-referenced-object")) + .containsEntry("bilbo", new SimpleObjectRef("ref-2", "me-the-2-referenced-object")); + } + + @Test // GH-3602 + void loadLazyCyclicReference() { + + WithRefA a = new WithRefA(); + a.id = "a"; + + WithRefB b = new WithRefB(); + b.id = "b"; + + a.toB = b; + b.lazyToA = a; + + template.save(a); + template.save(b); + + WithRefA loadedA = template.query(WithRefA.class).matching(where("id").is(a.id)).firstValue(); + assertThat(loadedA).isNotNull(); + assertThat(loadedA.getToB()).isNotNull(); + LazyLoadingTestUtils.assertProxy(loadedA.getToB().lazyToA, (proxy) -> { + + assertThat(proxy.isResolved()).isFalse(); + assertThat(proxy.currentValue()).isNull(); + }); + } + + @Test // GH-3602 + void loadEagerCyclicReference() { + + WithRefA a = new WithRefA(); + a.id = "a"; + + WithRefB b = new WithRefB(); + b.id = "b"; + + a.toB = b; + b.eagerToA = a; + + template.save(a); + template.save(b); + + WithRefA loadedA = template.query(WithRefA.class).matching(where("id").is(a.id)).firstValue(); + + assertThat(loadedA).isNotNull(); + assertThat(loadedA.getToB()).isNotNull(); + assertThat(loadedA.getToB().eagerToA).isSameAs(loadedA); + } + + @Test // GH-3602 + void loadAndStoreUnresolvedLazyDoesNotResolveTheProxy() { + + String collectionB = template.getCollectionName(WithRefB.class); + + WithRefA a = new WithRefA(); + a.id = "a"; + + WithRefB b = new WithRefB(); + b.id = "b"; + + a.toB = b; + b.lazyToA = a; + + template.save(a); + template.save(b); + + WithRefA loadedA = template.query(WithRefA.class).matching(where("id").is(a.id)).firstValue(); + template.save(loadedA.getToB()); + + LazyLoadingTestUtils.assertProxy(loadedA.getToB().lazyToA, (proxy) -> { + + assertThat(proxy.isResolved()).isFalse(); + assertThat(proxy.currentValue()).isNull(); + }); + + Document target = template.execute(db -> { + return db.getCollection(collectionB).find(Filters.eq("_id", "b")).first(); + }); + assertThat(target.get("lazyToA", Object.class)).isEqualTo("a"); + } + + @Test // GH-3602 + void loadCollectionReferenceWithMissingRefs() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + String refCollectionName = template.getCollectionName(SimpleObjectRef.class); + + // ref-1 is missing. + Document refSource = new Document("_id", "ref-2").append("value", "me-the-2-referenced-object"); + Document source = new Document("_id", "id-1").append("value", "v1").append("simpleValueRef", + Arrays.asList("ref-1", "ref-2")); + + template.execute(db -> { + + db.getCollection(refCollectionName).insertOne(refSource); + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.getSimpleValueRef()).containsExactly(new SimpleObjectRef("ref-2", "me-the-2-referenced-object")); + } + + @Test // GH-3602 + void queryForReference() { + + WithRefB b = new WithRefB(); + b.id = "b"; + template.save(b); + + WithRefA a = new WithRefA(); + a.id = "a"; + a.toB = b; + template.save(a); + + WithRefA a2 = new WithRefA(); + a2.id = "a2"; + template.save(a2); + + WithRefA loadedA = template.query(WithRefA.class).matching(where("toB").is(b)).firstValue(); + assertThat(loadedA.getId()).isEqualTo(a.getId()); + } + + @Test // GH-3602 + void queryForReferenceInCollection() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + Document shouldBeFound = new Document("_id", "id-1").append("value", "v1").append("simpleValueRef", + Arrays.asList("ref-1", "ref-2")); + Document shouldNotBeFound = new Document("_id", "id-2").append("value", "v2").append("simpleValueRef", + Arrays.asList("ref-1")); + + template.execute(db -> { + + db.getCollection(rootCollectionName).insertOne(shouldBeFound); + db.getCollection(rootCollectionName).insertOne(shouldNotBeFound); + return null; + }); + + SimpleObjectRef objectRef = new SimpleObjectRef("ref-2", "some irrelevant value"); + + List loaded = template.query(CollectionRefRoot.class) + .matching(where("simpleValueRef").in(objectRef)).all(); + assertThat(loaded).map(CollectionRefRoot::getId).containsExactly("id-1"); + } + + @Test // GH-3602 + void queryForReferenceOnIdField() { + + WithRefB b = new WithRefB(); + b.id = "b"; + template.save(b); + + WithRefA a = new WithRefA(); + a.id = "a"; + a.toB = b; + template.save(a); + + WithRefA a2 = new WithRefA(); + a2.id = "a2"; + template.save(a2); + + WithRefA loadedA = template.query(WithRefA.class).matching(where("toB.id").is(b.id)).firstValue(); + assertThat(loadedA.getId()).isEqualTo(a.getId()); + } + + @Test // GH-3602 + void updateReferenceWithEntityHavingPointerConversion() { + + WithRefB b = new WithRefB(); + b.id = "b"; + template.save(b); + + WithRefA a = new WithRefA(); + a.id = "a"; + template.save(a); + + template.update(WithRefA.class).apply(new Update().set("toB", b)).first(); + + String collectionA = template.getCollectionName(WithRefA.class); + + Document target = template.execute(db -> { + return db.getCollection(collectionA).find(Filters.eq("_id", "a")).first(); + }); + + assertThat(target).containsEntry("toB", "b"); + } + + @Test // GH-3602 + void updateReferenceWithEntityWithoutPointerConversion() { + + String collectionName = template.getCollectionName(SingleRefRoot.class); + SingleRefRoot refRoot = new SingleRefRoot(); + refRoot.id = "root-1"; + + SimpleObjectRef ref = new SimpleObjectRef("ref-1", "me the referenced object"); + + template.save(refRoot); + + template.update(SingleRefRoot.class).apply(new Update().set("simpleValueRef", ref)).first(); + + Document target = template.execute(db -> { + return db.getCollection(collectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target).containsEntry("simpleValueRef", "ref-1"); + } + + @Test // GH-3602 + void updateReferenceWithValue() { + + WithRefA a = new WithRefA(); + a.id = "a"; + template.save(a); + + template.update(WithRefA.class).apply(new Update().set("toB", "b")).first(); + + String collectionA = template.getCollectionName(WithRefA.class); + + Document target = template.execute(db -> { + return db.getCollection(collectionA).find(Filters.eq("_id", "a")).first(); + }); + + assertThat(target).containsEntry("toB", "b"); + } + + @Test // GH-3602 + void updateReferenceCollectionWithEntity() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + CollectionRefRoot root = new CollectionRefRoot(); + root.id = "root-1"; + root.simpleValueRef = Collections.singletonList(new SimpleObjectRef("ref-1", "beastie")); + + template.save(root); + + template.update(CollectionRefRoot.class) + .apply(new Update().push("simpleValueRef").value(new SimpleObjectRef("ref-2", "boys"))).first(); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target).containsEntry("simpleValueRef", Arrays.asList("ref-1", "ref-2")); + } + + @Test // GH-3602 + void updateReferenceCollectionWithValue() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + CollectionRefRoot root = new CollectionRefRoot(); + root.id = "root-1"; + root.simpleValueRef = Collections.singletonList(new SimpleObjectRef("ref-1", "beastie")); + + template.save(root); + + template.update(CollectionRefRoot.class).apply(new Update().push("simpleValueRef").value("ref-2")).first(); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target).containsEntry("simpleValueRef", Arrays.asList("ref-1", "ref-2")); + } + + @Test // GH-3602 + @Disabled("Property path resolution does not work inside maps, the key is considered :/") + void updateReferenceMapWithEntity() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + CollectionRefRoot root = new CollectionRefRoot(); + root.id = "root-1"; + root.mapValueRef = Collections.singletonMap("beastie", new SimpleObjectRef("ref-1", "boys")); + + template.save(root); + + template.update(CollectionRefRoot.class) + .apply(new Update().set("mapValueRef.rise", new SimpleObjectRef("ref-2", "against"))).first(); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target).containsEntry("mapValueRef", new Document("beastie", "ref-1").append("rise", "ref-2")); + } + + @Test // GH-3602 + void updateReferenceMapWithValue() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + CollectionRefRoot root = new CollectionRefRoot(); + root.id = "root-1"; + root.mapValueRef = Collections.singletonMap("beastie", new SimpleObjectRef("ref-1", "boys")); + + template.save(root); + + template.update(CollectionRefRoot.class).apply(new Update().set("mapValueRef.rise", "ref-2")).first(); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target).containsEntry("mapValueRef", new Document("beastie", "ref-1").append("rise", "ref-2")); + } + + @Test // GH-3602 + void useReadingWriterConverterPairForLoading() { + + SingleRefRoot root = new SingleRefRoot(); + root.id = "root-1"; + root.withReadingConverter = new SimpleObjectRefWithReadingConverter("ref-1", "value-1"); + + template.save(root.withReadingConverter); + + template.save(root); + + Document target = template.execute(db -> { + return db.getCollection(template.getCollectionName(SingleRefRoot.class)).find(Filters.eq("_id", root.id)).first(); + }); + + assertThat(target).containsEntry("withReadingConverter", + new Document("ref-key-from-custom-write-converter", root.withReadingConverter.id)); + + SingleRefRoot loaded = template.findOne(query(where("id").is(root.id)), SingleRefRoot.class); + assertThat(loaded.withReadingConverter).isInstanceOf(SimpleObjectRefWithReadingConverter.class); + } + + @Test // GH-3602 + void deriveMappingFromLookup() { + + Publisher publisher = new Publisher(); + publisher.id = "p-1"; + publisher.acronym = "TOR"; + publisher.name = "Tom Doherty Associates"; + + template.save(publisher); + + Book book = new Book(); + book.id = "book-1"; + book.publisher = publisher; + + template.save(book); + + Document target = template.execute(db -> { + return db.getCollection(template.getCollectionName(Book.class)).find(Filters.eq("_id", book.id)).first(); + }); + + assertThat(target).containsEntry("publisher", new Document("acc", publisher.acronym).append("n", publisher.name)); + + Book result = template.findOne(query(where("id").is(book.id)), Book.class); + assertThat(result.publisher).isNotNull(); + } + + @Test // GH-3602 + void updateDerivedMappingFromLookup() { + + Publisher publisher = new Publisher(); + publisher.id = "p-1"; + publisher.acronym = "TOR"; + publisher.name = "Tom Doherty Associates"; + + template.save(publisher); + + Book book = new Book(); + book.id = "book-1"; + + template.save(book); + + template.update(Book.class).matching(where("id").is(book.id)).apply(new Update().set("publisher", publisher)).first(); + + Document target = template.execute(db -> { + return db.getCollection(template.getCollectionName(Book.class)).find(Filters.eq("_id", book.id)).first(); + }); + + assertThat(target).containsEntry("publisher", new Document("acc", publisher.acronym).append("n", publisher.name)); + + Book result = template.findOne(query(where("id").is(book.id)), Book.class); + assertThat(result.publisher).isNotNull(); + } + + @Test // GH-3602 + void queryDerivedMappingFromLookup() { + + Publisher publisher = new Publisher(); + publisher.id = "p-1"; + publisher.acronym = "TOR"; + publisher.name = "Tom Doherty Associates"; + + template.save(publisher); + + Book book = new Book(); + book.id = "book-1"; + book.publisher = publisher; + + template.save(book); + book.publisher = publisher; + + Book result = template.findOne(query(where("publisher").is(publisher)), Book.class); + assertThat(result.publisher).isNotNull(); } @Data @@ -556,16 +959,16 @@ static class SimpleObjectRef { @Id String id; String value; - } @Getter @Setter static class SimpleObjectRefWithReadingConverter extends SimpleObjectRef { - public SimpleObjectRefWithReadingConverter(String id, String value, String id1, String value1) { + public SimpleObjectRefWithReadingConverter(String id, String value) { super(id, value); } + } @Data @@ -609,41 +1012,94 @@ public Object toReference() { } } - static class ReferencableConverter implements Converter { + static class ReferencableConverter implements Converter { @Nullable @Override - public ObjectReference convert(ReferenceAble source) { + public DocumentPointer convert(ReferenceAble source) { return source::toReference; } } @WritingConverter class DocumentToSimpleObjectRefWithReadingConverter - implements Converter, SimpleObjectRefWithReadingConverter> { + implements Converter, SimpleObjectRefWithReadingConverter> { - private final MongoTemplate template; + @Nullable + @Override + public SimpleObjectRefWithReadingConverter convert(DocumentPointer source) { - public DocumentToSimpleObjectRefWithReadingConverter(MongoTemplate template) { - this.template = template; + Document document = client.getDatabase(DB_NAME).getCollection("simple-object-ref") + .find(Filters.eq("_id", source.getPointer().get("ref-key-from-custom-write-converter"))).first(); + return new SimpleObjectRefWithReadingConverter(document.getString("_id"), document.getString("value")); } + } + + @WritingConverter + class SimpleObjectRefWithReadingConverterToDocumentConverter + implements Converter> { @Nullable @Override - public SimpleObjectRefWithReadingConverter convert(ObjectReference source) { - return template.findOne(query(where("id").is(source.getPointer().get("the-ref-key-you-did-not-expect"))), - SimpleObjectRefWithReadingConverter.class); + public DocumentPointer convert(SimpleObjectRefWithReadingConverter source) { + return () -> new Document("ref-key-from-custom-write-converter", source.getId()); } } - @WritingConverter - class SimpleObjectRefWithReadingConverterToDocumentConverter - implements Converter> { + @Getter + @Setter + static class WithRefA/* to B */ implements ReferenceAble { + + @Id String id; + @DocumentReference WithRefB toB; + + @Override + public Object toReference() { + return id; + } + } + + @Getter + @Setter + @ToString + static class WithRefB/* to A */ implements ReferenceAble { + + @Id String id; + @DocumentReference(lazy = true) WithRefA lazyToA; + + @DocumentReference WithRefA eagerToA; + + @Override + public Object toReference() { + return id; + } + } + + static class ReferencedObject {} + + class ToDocumentPointerConverter implements Converter> { @Nullable @Override - public ObjectReference convert(SimpleObjectRefWithReadingConverter source) { - return () -> new Document("the-ref-key-you-did-not-expect", source.getId()); + public DocumentPointer convert(ReferencedObject source) { + return () -> new Document("", source); } } + + @Data + static class Book { + + String id; + + @DocumentReference(lookup = "{ 'acronym' : ?#{acc}, 'name' : ?#{n} }") Publisher publisher; + + } + + static class Publisher { + + String id; + String acronym; + String name; + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index c0a6b8df90..d7a2870477 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -33,6 +33,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; + import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; @@ -64,8 +65,6 @@ void setUp() { when(factoryMock.getMongoDatabase()).thenReturn(dbMock); when(dbMock.getCollection(anyString(), any(Class.class))).thenReturn(collectionMock); when(collectionMock.find(any(Document.class))).thenReturn(cursorMock); - when(cursorMock.sort(any(Document.class))).thenReturn(cursorMock); - when(cursorMock.spliterator()).thenReturn(Collections. emptyList().spliterator()); resolver = new DefaultDbRefResolver(factoryMock); } @@ -116,7 +115,7 @@ void bulkFetchShouldRestoreOriginalOrder() { DBRef ref1 = new DBRef("collection-1", o1.get("_id")); DBRef ref2 = new DBRef("collection-1", o2.get("_id")); - when(cursorMock.spliterator()).thenReturn(Arrays.asList(o2, o1).spliterator()); + when(cursorMock.into(any())).then(invocation -> Arrays.asList(o2, o1)); assertThat(resolver.bulkFetch(Arrays.asList(ref1, ref2))).containsExactly(o1, o2); } @@ -129,7 +128,7 @@ void bulkFetchContainsDuplicates() { DBRef ref1 = new DBRef("collection-1", document.get("_id")); DBRef ref2 = new DBRef("collection-1", document.get("_id")); - when(cursorMock.spliterator()).thenReturn(Arrays.asList(document).spliterator()); + when(cursorMock.into(any())).then(invocation -> Arrays.asList(document)); assertThat(resolver.bulkFetch(Arrays.asList(ref1, ref2))).containsExactly(document, document); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index e2f69260b1..9c157db759 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -48,6 +48,7 @@ import org.springframework.data.mongodb.core.geo.GeoJsonPolygon; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.FieldType; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -1487,4 +1488,32 @@ static class WithPropertyUsingUnderscoreInName { @Field("renamed") String renamed_fieldname_with_underscores; } + + static class WithDocumentReferences { + + @DocumentReference + Sample sample; + + @DocumentReference + SimpeEntityWithoutId noId; + + @DocumentReference(lookup = "{ 'stringProperty' : ?#{stringProperty} }") + SimpeEntityWithoutId noIdButLookupQuery; + + } + + @Test + void xxx() { + + Sample sample = new Sample(); + sample.foo = "sample-id"; + + Query query = query(where("sample").is(sample)); + + org.bson.Document mappedObject = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WithDocumentReferences.class)); + + System.out.println("mappedObject.toJson(): " + mappedObject.toJson()); + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java index 9aa1bb0b57..b70930dae0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java @@ -18,11 +18,10 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; -import org.bson.conversions.Bson; import org.springframework.data.mongodb.core.convert.ReferenceLoader; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.ReferenceFilter; +import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; import org.springframework.data.mongodb.core.convert.ReferenceReader; -import org.springframework.data.util.Streamable; +import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -107,7 +106,7 @@ public void setUp() throws Exception { @Nullable @Override - public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, BiFunction> lookupFunction) { + public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction) { return null; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 9ab37e3ff5..61caa30560 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -1434,4 +1434,19 @@ void annotatedQueryShouldAllowAggregationInProjection() { Person target = repository.findWithAggregationInProjection(alicia.getId()); assertThat(target.getFirstname()).isEqualTo(alicia.getFirstname().toUpperCase()); } + + @Test // GH-3602 + void executesQueryWithDocumentReferenceCorrectly() { + + Person josh = new Person("Josh", "Long"); + User dave = new User(); + dave.id = "dave"; + + josh.setSpiritAnimal(dave); + + operations.save(josh); + + List result = repository.findBySpiritAnimal(dave); + assertThat(result).map(Person::getId).containsExactly(josh.getId()); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java index 01b0c28de2..62c5b18be5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java @@ -27,6 +27,7 @@ import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.Unwrapped; @@ -74,6 +75,9 @@ public enum Sex { @Unwrapped.Nullable(prefix = "u") // User unwrappedUser; + @DocumentReference + User spiritAnimal; + public Person() { this(null, null); @@ -308,6 +312,14 @@ public void setUnwrappedUser(User unwrappedUser) { this.unwrappedUser = unwrappedUser; } + public User getSpiritAnimal() { + return spiritAnimal; + } + + public void setSpiritAnimal(User spiritAnimal) { + this.spiritAnimal = spiritAnimal; + } + /* * (non-Javadoc) * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 314655e781..ca382fa2ca 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -416,4 +416,6 @@ Person findPersonByManyArguments(String firstname, String lastname, String email List findByUnwrappedUserUsername(String username); List findByUnwrappedUser(User user); + + List findBySpiritAnimal(User user); } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 03d18bacf9..842dd8341b 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,6 +1,11 @@ [[new-features]] = New & Noteworthy +[[new-features.3.3]] +== What's New in Spring Data MongoDB 3.3 + +* Extended support for <> entities. + [[new-features.3.2]] == What's New in Spring Data MongoDB 3.2 diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 82b5632f2b..1998fe1ad8 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -480,6 +480,7 @@ The MappingMongoConverter can use metadata to drive the mapping of objects to do * `@MongoId`: Applied at the field level to mark the field used for identity purpose. Accepts an optional `FieldType` to customize id conversion. * `@Document`: Applied at the class level to indicate this class is a candidate for mapping to the database. You can specify the name of the collection where the data will be stored. * `@DBRef`: Applied at the field to indicate it is to be stored using a com.mongodb.DBRef. +* `@DocumentReference`: Applied at the field to indicate it is to be stored as a pointer to another document. This can be a single value (the _id_ by default), or a `Document` provided via a converter. * `@Indexed`: Applied at the field level to describe how to index the field. * `@CompoundIndex` (repeatable): Applied at the type level to declare Compound Indexes. * `@GeoSpatialIndexed`: Applied at the field level to describe how to geoindex the field. @@ -826,6 +827,370 @@ Required properties that are also defined as lazy loading ``DBRef`` and used as TIP: Lazily loaded ``DBRef``s can be hard to debug. Make sure tooling does not accidentally trigger proxy resolution by eg. calling `toString()` or some inline debug rendering invoking property getters. Please consider to enable _trace_ logging for `org.springframework.data.mongodb.core.convert.DefaultDbRefResolver` to gain insight on `DBRef` resolution. +[[mapping-usage.linking]] +=== Using Document References + +Using `@DocumentReference` offers an alternative way of linking entities in MongoDB. +While the goal is the same as when using <>, the store representation is different. +`DBRef` resolves to a document with a fixed structure as outlined in the https://docs.mongodb.com/manual/reference/database-references/[MongoDB Reference documentation]. + +Document references, do not follow a specific format. +They can be literally anything, a single value, an entire document, basically everything that can be stored in MongoDB. +By default, the mapping layer will use the referenced entities _id_ value for storage and retrieval, like in the sample below. + +==== +[source,java] +---- +@Document +public class Account { + + @Id + private String id; + private Float total; +} + +@Document +public class Person { + + @Id + private String id; + + @DocumentReference <1> + private List accounts; +} +---- +[source,java] +---- +Account account = ... + +tempate.insert(account); <2> + +template.update(Person.class) + .matching(where("id").is(...)) + .apply(new Update().push("accounts").value(account)) <3> + .first(); +---- +[source,json] +---- +{ + "_id" : ..., + "accounts" : [ "6509b9e", ... ] <4> +} +---- +<1> Mark the collection of `Account` values to be linked. +<2> The mapping framework does not handle cascading saves, so make sure to persist the referenced entity individually. +<3> Add the reference to the existing entity. +<4> Linked `Account` entities are represented as an array of their `_id` values. +==== + +The sample above uses an `_id` based fetch query (`{ '_id' : ?#{#target} }`) for data retrieval and resolves linked entities eagerly. +It is possible to alter resolution defaults (listed below) via the attributes of `@DocumentReference` + +.@DocumentReference defaults +[cols="2,3,5", options="header"] +|=== +| Attribute | Description | Default + +| `db` +| The target database name for collection lookup. +| The configured database provided by `MongoDatabaseFactory.getMongoDatabase()`. + +| `collection` +| The target collection name. +| The annotated properties domain type, respectively the value type in case of `Collection` like or `Map` properties, collection name. + +| `lookup` +| The single document lookup query evaluating placeholders via SpEL expressions using `#target` as the marker for a given source value. `Collection` like or `Map` properties combine individual lookups via an `$or` operator. +| An `_id` field based query (`{ '_id' : ?#{#target} }`) using the loaded source value. + +| `lazy` +| If set to `true` value resolution is delayed upon first access of the property. +| Resolves properties eagerly by default. +|=== + +`@DocumentReference(lookup=...)` allows to define custom queries that are independent from the `_id` field and therefore offer a flexible way of defining links between entities as demonstrated in the sample below, where the `Publisher` of a book is referenced by its acronym instead of the internal `id`. + +==== +[source,java] +---- +@Document +public class Book { + + @Id + private ObjectId id; + private String title; + private List author; + + @Field("publisher_ac") + @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") <1> + private Publisher publisher; +} + +@Document +public class Publisher { + + @Id + private ObjectId id; + private String acronym; <1> + private String name; + + @DocumentReference(lazy = true) <2> + private List books; + +} +---- +[source,json] +---- +{ + "_id" : 9a48e32, + "title" : "The Warded Man", + "author" : ["Peter V. Brett"], + "publisher_ac" : "DR" +} +---- +<1> Use the `acronym` field to query for entities in the `Publisher` collection. +<2> Lazy load back references to the `Book` collection. +==== + +The above snipped shows the reading side of things when working with custom linked objects. +To make the writing part aware of the modified document pointer a custom converter, capable of the transformation into a `DocumentPointer`, like the one below, needs to be registered. + +==== +[source,java] +---- +@WritingConverter +class PublisherReferenceConverter implements Converter> { + + @Override + public DocumentPointer convert(Publisher source) { + return () -> source.getAcronym(); + } +} +---- +==== + +If no `DocumentPointer` converter is provided the target linkage document can be computed based on the given lookup query. +In this case the association target properties are evaluated as shown in the following sample. + +==== +[source,java] +---- +@Document +public class Book { + + @Id + private ObjectId id; + private String title; + private List author; + + @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") <1> <2> + private Publisher publisher; +} + +@Document +public class Publisher { + + @Id + private ObjectId id; + private String acronym; <1> + private String name; + + // ... +} +---- +[source,json] +---- +{ + "_id" : 9a48e32, + "title" : "The Warded Man", + "author" : ["Peter V. Brett"], + "publisher" : { + "acc" : "DOC" + } +} +---- +<1> Use the `acronym` field to query for entities in the `Publisher` collection. +<2> The field value placeholders of the lookup query (like `acc`) is used to form the linkage document. +==== + +With all the above in place it is possible to model all kind of associations between entities. +Have a look at the non exhaustive list of samples below to get feeling for what is possible. + +.Simple Document Reference using _id_ field +==== +[source,java] +---- +class Entity { + @DocumentReference + private ReferencedObject ref; +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : "9a48e32" <1> +} + +// referenced object +{ + "_id" : "9a48e32" <1> +} +---- +<1> MongoDB simple type can be directly used without further configuration. +==== + +.Simple Document Reference using _id_ field with explicit lookup query +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") <1> + private ReferencedObject ref; +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : "9a48e32" <1> +} + +// referenced object +{ + "_id" : "9a48e32" +} +---- +<1> _target_ defines the linkage value itself. +==== + +.Document Reference extracting field of linkage document for lookup query +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ '_id' : '?#{refKey}' }") <1> <2> + private ReferencedObject ref; +} +---- + +[source,java] +---- +@WritingConverter +class ToDocumentPointerConverter implements Converter> { + public DocumentPointer convert(ReferencedObject source) { + return () -> new Document("refKey", source.id); <1> + } +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : { + "refKey" : "9a48e32" <1> + } +} + +// referenced object +{ + "_id" : "9a48e32" +} +---- +<1> The key used for obtaining the linkage value must be the one used during write. +<2> `refKey` is short for `target.refKey`. +==== + +.Document Reference with multiple values forming the lookup query +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ 'firstname' : '?#{fn}', 'lastname' : '?#{ln}' }") <1> <2> + private ReferencedObject ref; +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : { + "fn" : "Josh", <1> + "ln" : "Long" <1> + } +} + +// referenced object +{ + "_id" : "9a48e32", + "firsntame" : "Josh", <2> + "lastname" : "Long", <2> +} +---- +<1> Read/wirte the keys `fn` & `ln` from/to the linkage document based on the lookup query. +<2> Use non _id_ fields for the lookup of the target documents. +==== + +.Document Reference reading target collection from linkage document +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ '_id' : '?#{id}' }", collection = "?#{collection}") <2> + private ReferencedObject ref; +} +---- + +[source,java] +---- +@WritingConverter +class ToDocumentPointerConverter implements Converter> { + public DocumentPointer convert(ReferencedObject source) { + return () -> new Document("id", source.id) <1> + .append("collection", ... ); <2> + } +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : { + "id" : "9a48e32", <1> + "collection" : "..." <2> + } +} +---- +<1> Read/wirte the keys `_id` from/to the linkage document to use them in the lookup query. +<2> The collection name can be read from the linkage document via its key. +==== + +[WARNING] +==== +We know it is tempting to use all kinds of MongoDB query operators in the lookup query and this is fine. But: + +* Make sure to have indexes in place that support your lookup. +* Mind that resolution takes time and consider a lazy strategy. +* A collection of document references is bulk loaded using an `$or` operator. + +The original element order is restored in memory which cannot be done when using MongoDB query operators. +In this case Results will be ordered as they are received from the store. + +And a few more general remarks: + +* Cyclic references? Ask your self if you need them. +* Lazy document references are hard to debug. Make sure tooling does not accidentally trigger proxy resolution by eg. calling `toString()`. +* There is no support for reading document references via the reactive bits Spring Data MongoDB offers. +==== + [[mapping-usage-events]] === Mapping Framework Events From 82af678caba783997f920d2fe00e0309f5667e9d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 18 May 2021 10:43:13 +0200 Subject: [PATCH 0427/1381] Polishing Rename ReferenceReader to ReferenceLookupDelegate. Rename LazyLoadingProxyGenerator to LazyLoadingProxyFactory. Rename DefaultReferenceLoader to MongoDatabaseFactoryReferenceLoader. Reduce scope of LookupFunction and move it to ReferenceLookupDelegate. Extract some checks into methods to reflect the underlying concepts. Simplify code, convert variables to constants where possible. Original pull request: #3647. Closes #3602. --- .../core/convert/DefaultDbRefResolver.java | 9 ++- .../convert/DefaultReferenceResolver.java | 32 +++++--- .../core/convert/DocumentPointerFactory.java | 39 +++++++--- ...ator.java => LazyLoadingProxyFactory.java} | 58 +++++++------- .../core/convert/MappingMongoConverter.java | 38 ++++++---- ... MongoDatabaseFactoryReferenceLoader.java} | 8 +- .../core/convert/NoOpDbRefResolver.java | 10 +-- .../mongodb/core/convert/ReferenceLoader.java | 30 +++++--- ...ader.java => ReferenceLookupDelegate.java} | 76 +++++++++++-------- .../core/convert/ReferenceResolver.java | 33 ++------ .../mapping/BasicMongoPersistentProperty.java | 2 +- .../core/convert/LazyLoadingTestUtils.java | 7 +- .../core/convert/QueryMapperUnitTests.java | 9 ++- .../BasicMongoPersistentEntityUnitTests.java | 6 +- .../performance/ReactivePerformanceTests.java | 13 ++-- 15 files changed, 204 insertions(+), 166 deletions(-) rename spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/{LazyLoadingProxyGenerator.java => LazyLoadingProxyFactory.java} (81%) rename spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/{DefaultReferenceLoader.java => MongoDatabaseFactoryReferenceLoader.java} (85%) rename spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/{ReferenceReader.java => ReferenceLookupDelegate.java} (84%) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 5277fbc0b0..f64c7f0f06 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -47,6 +47,7 @@ import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoDatabaseUtils; import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; +import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisStd; @@ -83,7 +84,7 @@ public class DefaultDbRefResolver extends DefaultReferenceResolver implements Db */ public DefaultDbRefResolver(MongoDatabaseFactory mongoDbFactory) { - super(new DefaultReferenceLoader(mongoDbFactory)); + super(new MongoDatabaseFactoryReferenceLoader(mongoDbFactory)); Assert.notNull(mongoDbFactory, "MongoDbFactory translator must not be null!"); @@ -117,7 +118,7 @@ public Object resolveDbRef(MongoPersistentProperty property, @Nullable DBRef dbr */ @Override public Document fetch(DBRef dbRef) { - return getReferenceLoader().fetch(DocumentReferenceQuery.singleReferenceFilter(Filters.eq("_id", dbRef.getId())), + return getReferenceLoader().fetchOne(DocumentReferenceQuery.forSingleDocument(Filters.eq("_id", dbRef.getId())), ReferenceCollection.fromDBRef(dbRef)); } @@ -159,7 +160,7 @@ public List bulkFetch(List refs) { } List result = mongoCollection // - .find(new Document("_id", new Document("$in", ids))) // + .find(new Document(BasicMongoPersistentProperty.ID_FIELD_NAME, new Document("$in", ids))) // .into(new ArrayList<>()); return ids.stream() // @@ -239,7 +240,7 @@ private boolean isLazyDbRef(MongoPersistentProperty property) { private static Stream documentWithId(Object identifier, Collection documents) { return documents.stream() // - .filter(it -> it.get("_id").equals(identifier)) // + .filter(it -> it.get(BasicMongoPersistentProperty.ID_FIELD_NAME).equals(identifier)) // .limit(1); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java index 0692f719b5..7e38b6995d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java @@ -15,7 +15,10 @@ */ package org.springframework.data.mongodb.core.convert; -import org.springframework.data.mongodb.core.mapping.DocumentReference; +import static org.springframework.data.mongodb.core.convert.ReferenceLookupDelegate.*; + +import java.util.Collections; + import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; @@ -37,21 +40,32 @@ public ReferenceLoader getReferenceLoader() { @Nullable @Override - public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction) { + public Object resolveReference(MongoPersistentProperty property, Object source, + ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader) { + + LookupFunction lookupFunction = (filter, ctx) -> { + if (property.isCollectionLike() || property.isMap()) { + return getReferenceLoader().fetchMany(filter, ctx); + + } + + Object target = getReferenceLoader().fetchOne(filter, ctx); + return target == null ? Collections.emptyList() + : Collections.singleton(getReferenceLoader().fetchOne(filter, ctx)); + }; if (isLazyReference(property)) { - return createLazyLoadingProxy(property, source, referenceReader, lookupFunction, resultConversionFunction); + return createLazyLoadingProxy(property, source, referenceLookupDelegate, lookupFunction, entityReader); } - return referenceReader.readReference(property, source, lookupFunction, resultConversionFunction); + return referenceLookupDelegate.readReference(property, source, lookupFunction, entityReader); } private Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, - ReferenceReader referenceReader, LookupFunction lookupFunction, - ResultConversionFunction resultConversionFunction) { - return new LazyLoadingProxyGenerator(referenceReader).createLazyLoadingProxy(property, source, lookupFunction, - resultConversionFunction); + ReferenceLookupDelegate referenceLookupDelegate, LookupFunction lookupFunction, + MongoEntityReader entityReader) { + return new LazyLoadingProxyFactory(referenceLookupDelegate).createLazyLoadingProxy(property, source, lookupFunction, + entityReader); } protected boolean isLazyReference(MongoPersistentProperty property) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java index a91a48d922..8e9554b6ba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java @@ -17,12 +17,14 @@ import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bson.Document; + import org.springframework.core.convert.ConversionService; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.context.MappingContext; @@ -37,9 +39,9 @@ */ class DocumentPointerFactory { - private ConversionService conversionService; - private MappingContext, MongoPersistentProperty> mappingContext; - private Map linkageMap; + private final ConversionService conversionService; + private final MappingContext, MongoPersistentProperty> mappingContext; + private final Map linkageMap; public DocumentPointerFactory(ConversionService conversionService, MappingContext, MongoPersistentProperty> mappingContext) { @@ -60,15 +62,24 @@ public DocumentPointer computePointer(MongoPersistentProperty property, Objec } else { MongoPersistentEntity persistentEntity = mappingContext - .getPersistentEntity(property.getAssociationTargetType()); + .getRequiredPersistentEntity(property.getAssociationTargetType()); - if (!property.getDocumentReference().lookup().toLowerCase().replaceAll("\\s", "").replaceAll("'", "") + // TODO: Extract method + if (!property.getDocumentReference().lookup().toLowerCase(Locale.ROOT).replaceAll("\\s", "").replaceAll("'", "") .equals("{_id:?#{#target}}")) { - return () -> linkageMap.computeIfAbsent(property.getDocumentReference().lookup(), key -> { - return new LinkageDocument(key); - }).get(persistentEntity, - BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(property.getOwner(), value)); + MongoPersistentEntity valueEntity = mappingContext.getPersistentEntity(value.getClass()); + PersistentPropertyAccessor propertyAccessor; + if (valueEntity == null) { + propertyAccessor = BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(property.getOwner(), + value); + } else { + propertyAccessor = valueEntity.getPropertyAccessor(value); + + } + + return () -> linkageMap.computeIfAbsent(property.getDocumentReference().lookup(), LinkageDocument::new) + .get(persistentEntity, propertyAccessor); } // just take the id as a reference @@ -78,6 +89,8 @@ public DocumentPointer computePointer(MongoPersistentProperty property, Objec static class LinkageDocument { + static final Pattern pattern = Pattern.compile("\\?#\\{#?[\\w\\d]*\\}"); + String lookup; org.bson.Document fetchDocument; Map mapMap; @@ -87,16 +100,18 @@ public LinkageDocument(String lookup) { this.lookup = lookup; String targetLookup = lookup; - Pattern pattern = Pattern.compile("\\?#\\{#?[\\w\\d]*\\}"); Matcher matcher = pattern.matcher(lookup); int index = 0; mapMap = new LinkedHashMap<>(); + + // TODO: Make explicit what's happening here while (matcher.find()) { String expr = matcher.group(); - mapMap.put(Integer.valueOf(index), expr.substring(0, expr.length() - 1).replace("?#{#", "").replace("?#{", "") - .replace("target.", "").replaceAll("'", "")); + String sanitized = expr.substring(0, expr.length() - 1).replace("?#{#", "").replace("?#{", "") + .replace("target.", "").replaceAll("'", ""); + mapMap.put(index, sanitized); targetLookup = targetLookup.replace(expr, index + ""); index++; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java similarity index 81% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java index 570a516d9b..8c2156df2e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyGenerator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java @@ -15,47 +15,46 @@ */ package org.springframework.data.mongodb.core.convert; +import static org.springframework.data.mongodb.core.convert.ReferenceLookupDelegate.*; import static org.springframework.util.ReflectionUtils.*; import java.io.Serializable; import java.lang.reflect.Method; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodProxy; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.LookupFunction; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.ResultConversionFunction; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.MongoEntityReader; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisStd; import org.springframework.util.ReflectionUtils; /** * @author Christoph Strobl */ -class LazyLoadingProxyGenerator { +class LazyLoadingProxyFactory { private final ObjenesisStd objenesis; - private final ReferenceReader referenceReader; + private final ReferenceLookupDelegate lookupDelegate; - public LazyLoadingProxyGenerator(ReferenceReader referenceReader) { + public LazyLoadingProxyFactory(ReferenceLookupDelegate lookupDelegate) { - this.referenceReader = referenceReader; + this.lookupDelegate = lookupDelegate; this.objenesis = new ObjenesisStd(true); } public Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, LookupFunction lookupFunction, - ResultConversionFunction resultConversionFunction) { + MongoEntityReader entityReader) { Class propertyType = property.getType(); - LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, source, referenceReader, lookupFunction, - resultConversionFunction); + LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, source, lookupDelegate, lookupFunction, + entityReader); if (!propertyType.isInterface()) { @@ -97,13 +96,13 @@ private Class getEnhancedTypeFor(Class type) { public static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor, Serializable { - private final ReferenceReader referenceReader; - MongoPersistentProperty property; + private final ReferenceLookupDelegate referenceLookupDelegate; + private final MongoPersistentProperty property; private volatile boolean resolved; - private @org.springframework.lang.Nullable Object result; - private Object source; - private LookupFunction lookupFunction; - private ResultConversionFunction resultConversionFunction; + private @Nullable Object result; + private final Object source; + private final LookupFunction lookupFunction; + private final MongoEntityReader entityReader; private final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD, GET_SOURCE_METHOD; @@ -118,22 +117,23 @@ public static class LazyLoadingInterceptor } } - public LazyLoadingInterceptor(MongoPersistentProperty property, Object source, ReferenceReader reader, - LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction) { + public LazyLoadingInterceptor(MongoPersistentProperty property, Object source, ReferenceLookupDelegate reader, + LookupFunction lookupFunction, MongoEntityReader entityReader) { this.property = property; this.source = source; - this.referenceReader = reader; + this.referenceLookupDelegate = reader; this.lookupFunction = lookupFunction; - this.resultConversionFunction = resultConversionFunction; + this.entityReader = entityReader; } @Nullable @Override - public Object invoke(@Nonnull MethodInvocation invocation) throws Throwable { + public Object invoke(MethodInvocation invocation) throws Throwable { return intercept(invocation.getThis(), invocation.getMethod(), invocation.getArguments(), null); } + @Nullable @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable { @@ -180,6 +180,7 @@ public Object intercept(Object o, Method method, Object[] args, MethodProxy prox return method.invoke(target, args); } + @Nullable private Object ensureResolved() { if (!resolved) { @@ -190,7 +191,7 @@ private Object ensureResolved() { return this.result; } - private String proxyToString(Object source) { + private String proxyToString(@Nullable Object source) { StringBuilder description = new StringBuilder(); if (source != null) { @@ -203,7 +204,7 @@ private String proxyToString(Object source) { return description.toString(); } - private boolean proxyEquals(@org.springframework.lang.Nullable Object proxy, Object that) { + private boolean proxyEquals(@Nullable Object proxy, Object that) { if (!(that instanceof LazyLoadingProxy)) { return false; @@ -216,11 +217,11 @@ private boolean proxyEquals(@org.springframework.lang.Nullable Object proxy, Obj return proxyToString(proxy).equals(that.toString()); } - private int proxyHashCode(@org.springframework.lang.Nullable Object proxy) { + private int proxyHashCode(@Nullable Object proxy) { return proxyToString(proxy).hashCode(); } - @org.springframework.lang.Nullable + @Nullable private synchronized Object resolve() { if (resolved) { @@ -238,7 +239,7 @@ private synchronized Object resolve() { // property.getOwner() != null ? property.getOwner().getName() : "unknown", property.getName()); // } - return referenceReader.readReference(property, source, lookupFunction, resultConversionFunction); + return referenceLookupDelegate.readReference(property, source, lookupFunction, entityReader); } catch (RuntimeException ex) { throw ex; @@ -254,4 +255,5 @@ private synchronized Object resolve() { } } } + } 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 2ad4d75230..8a77b51e2f 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 @@ -38,6 +38,7 @@ 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; @@ -63,6 +64,7 @@ import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider; import org.springframework.data.mongodb.CodecRegistryProvider; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.DocumentPointer; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; @@ -114,7 +116,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App protected final QueryMapper idMapper; protected final DbRefResolver dbRefResolver; protected final DefaultDbRefProxyHandler dbRefProxyHandler; - protected final ReferenceReader referenceReader; + protected final ReferenceLookupDelegate referenceLookupDelegate; protected @Nullable ApplicationContext applicationContext; protected MongoTypeMapper typeMapper; @@ -123,7 +125,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App private SpELContext spELContext; private @Nullable EntityCallbacks entityCallbacks; - private DocumentPointerFactory documentPointerFactory; + private final DocumentPointerFactory documentPointerFactory; /** * Creates a new {@link MappingMongoConverter} given the new {@link DbRefResolver} and {@link MappingContext}. @@ -154,7 +156,7 @@ public MappingMongoConverter(DbRefResolver dbRefResolver, return MappingMongoConverter.this.getValueInternal(context, prop, bson, evaluator); }); - this.referenceReader = new ReferenceReader(mappingContext, () -> spELContext); + this.referenceLookupDelegate = new ReferenceLookupDelegate(mappingContext, spELContext); this.documentPointerFactory = new DocumentPointerFactory(conversionService, mappingContext); } @@ -361,16 +363,15 @@ private ParameterValueProvider getParameterProvider(Con parameterProvider); } - private S read(ConversionContext context, MongoPersistentEntity entity, Document bson) { + private S read(ConversionContext context, MongoPersistentEntity entity, Document bson) { SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext); DocumentAccessor documentAccessor = new DocumentAccessor(bson); - if (bson.get("_id") != null) { - - Object existing = context.getPath().getPathItem(bson.get("_id"), entity.getCollection(), entity.getType()); + if (hasIdentifier(bson)) { + S existing = findContextualEntity(context, entity, bson); if (existing != null) { - return (S) existing; + return existing; } } @@ -391,6 +392,16 @@ private S read(ConversionContext context, MongoPersistentEnti return instance; } + private boolean hasIdentifier(Document bson) { + return bson.get(BasicMongoPersistentProperty.ID_FIELD_NAME) != null; + } + + @Nullable + private S findContextualEntity(ConversionContext context, MongoPersistentEntity entity, Document bson) { + return context.getPath().getPathItem(bson.get(BasicMongoPersistentProperty.ID_FIELD_NAME), entity.getCollection(), + entity.getType()); + } + private S populateProperties(ConversionContext context, MongoPersistentEntity entity, DocumentAccessor documentAccessor, SpELExpressionEvaluator evaluator, S instance) { @@ -509,7 +520,7 @@ private void readAssociation(Association association, P ConversionContext context, SpELExpressionEvaluator evaluator) { MongoPersistentProperty property = association.getInverse(); - final Object value = documentAccessor.get(property); + Object value = documentAccessor.get(property); if (value == null) { return; @@ -521,18 +532,13 @@ private void readAssociation(Association association, P if (conversionService.canConvert(DocumentPointer.class, property.getActualType())) { - DocumentPointer pointer = new DocumentPointer() { - @Override - public Object getPointer() { - return value; - } - }; + DocumentPointer pointer = () -> value; // collection like special treatment accessor.setProperty(property, conversionService.convert(pointer, property.getActualType())); } else { accessor.setProperty(property, - dbRefResolver.resolveReference(property, value, referenceReader, context::convert)); + dbRefResolver.resolveReference(property, value, referenceLookupDelegate, context::convert)); } return; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java similarity index 85% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java index 66b698077b..2483f57543 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java @@ -29,13 +29,13 @@ /** * @author Christoph Strobl */ -public class DefaultReferenceLoader implements ReferenceLoader { +public class MongoDatabaseFactoryReferenceLoader implements ReferenceLoader { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultReferenceLoader.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MongoDatabaseFactoryReferenceLoader.class); private final MongoDatabaseFactory mongoDbFactory; - public DefaultReferenceLoader(MongoDatabaseFactory mongoDbFactory) { + public MongoDatabaseFactoryReferenceLoader(MongoDatabaseFactory mongoDbFactory) { Assert.notNull(mongoDbFactory, "MongoDbFactory translator must not be null!"); @@ -43,7 +43,7 @@ public DefaultReferenceLoader(MongoDatabaseFactory mongoDbFactory) { } @Override - public Iterable bulkFetch(DocumentReferenceQuery filter, ReferenceCollection context) { + public Iterable fetchMany(DocumentReferenceQuery filter, ReferenceCollection context) { MongoCollection collection = getCollection(context); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java index 8b6c969439..41d7ab3c12 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java @@ -16,13 +16,10 @@ package org.springframework.data.mongodb.core.convert; import java.util.List; -import java.util.function.BiFunction; -import java.util.stream.Stream; import org.bson.Document; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; + import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; -import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import com.mongodb.DBRef; @@ -76,9 +73,8 @@ private T handle() throws UnsupportedOperationException { @Nullable @Override - public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - LookupFunction lookupFunction, - ResultConversionFunction resultConversionFunction) { + public Object resolveReference(MongoPersistentProperty property, Object source, + ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader) { return null; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java index d5c72afad8..7cfd5e3153 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java @@ -31,13 +31,13 @@ public interface ReferenceLoader { @Nullable - default Document fetch(DocumentReferenceQuery filter, ReferenceCollection context) { + default Document fetchOne(DocumentReferenceQuery filter, ReferenceCollection context) { - Iterator it = bulkFetch(filter, context).iterator(); + Iterator it = fetchMany(filter, context).iterator(); return it.hasNext() ? it.next() : null; } - Iterable bulkFetch(DocumentReferenceQuery filter, ReferenceCollection context); + Iterable fetchMany(DocumentReferenceQuery filter, ReferenceCollection context); interface DocumentReferenceQuery { @@ -52,16 +52,12 @@ default Bson getSort() { default Iterable apply(MongoCollection collection) { return restoreOrder(collection.find(getFilter()).sort(getSort())); } - + default Iterable restoreOrder(Iterable documents) { return documents; } - static DocumentReferenceQuery referenceFilter(Bson bson) { - return () -> bson; - } - - static DocumentReferenceQuery singleReferenceFilter(Bson bson) { + static DocumentReferenceQuery forSingleDocument(Bson bson) { return new DocumentReferenceQuery() { @@ -78,6 +74,22 @@ public Iterable apply(MongoCollection collection) { } }; } + + static DocumentReferenceQuery forManyDocuments(Bson bson) { + + return new DocumentReferenceQuery() { + + @Override + public Bson getFilter() { + return bson; + } + + @Override + public Iterable apply(MongoCollection collection) { + return collection.find(getFilter()).sort(getSort()); + } + }; + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java similarity index 84% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index fb37367b1d..3c441c1388 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -29,12 +29,12 @@ import org.bson.Document; import org.bson.conversions.Bson; + import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.SpELContext; import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.LookupFunction; +import org.springframework.data.mongodb.core.convert.ReferenceResolver.MongoEntityReader; import org.springframework.data.mongodb.core.convert.ReferenceResolver.ReferenceCollection; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.ResultConversionFunction; import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; @@ -42,58 +42,59 @@ import org.springframework.data.mongodb.util.json.ParameterBindingContext; import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; import org.springframework.data.mongodb.util.json.ValueProvider; -import org.springframework.data.util.Lazy; import org.springframework.data.util.Streamable; import org.springframework.expression.EvaluationContext; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import com.mongodb.DBRef; import com.mongodb.client.MongoCollection; /** + * A common delegate for {@link ReferenceResolver} implementations to resolve a reference to one/many target documents + * that are converted to entities. + * * @author Christoph Strobl + * @author Mark Paluch */ -public class ReferenceReader { +public final class ReferenceLookupDelegate { - private final Lazy, MongoPersistentProperty>> mappingContext; - private final Supplier spelContextSupplier; + private final MappingContext, MongoPersistentProperty> mappingContext; + private final SpELContext spELContext; private final ParameterBindingDocumentCodec codec; - public ReferenceReader(MappingContext, MongoPersistentProperty> mappingContext, - Supplier spelContextSupplier) { - - this(() -> mappingContext, spelContextSupplier); - } + public ReferenceLookupDelegate( + MappingContext, MongoPersistentProperty> mappingContext, + SpELContext spELContext) { - public ReferenceReader( - Supplier, MongoPersistentProperty>> mappingContextSupplier, - Supplier spelContextSupplier) { + Assert.notNull(mappingContext, "MappingContext must not be null"); + Assert.notNull(spELContext, "SpELContext must not be null"); - this.mappingContext = Lazy.of(mappingContextSupplier); - this.spelContextSupplier = spelContextSupplier; + this.mappingContext = mappingContext; + this.spELContext = spELContext; this.codec = new ParameterBindingDocumentCodec(); } + @Nullable Object readReference(MongoPersistentProperty property, Object value, LookupFunction lookupFunction, - ResultConversionFunction resultConversionFunction) { + MongoEntityReader entityReader) { - SpELContext spELContext = spelContextSupplier.get(); DocumentReferenceQuery filter = computeFilter(property, value, spELContext); ReferenceCollection referenceCollection = computeReferenceContext(property, value, spELContext); Iterable result = lookupFunction.apply(filter, referenceCollection); - if (!result.iterator().hasNext()) { - return null; + if (property.isCollectionLike()) { + return entityReader.read(result, property.getTypeInformation()); } - if (property.isCollectionLike()) { - return resultConversionFunction.apply(result, property.getTypeInformation()); + if (!result.iterator().hasNext()) { + return null; } - return resultConversionFunction.apply(result.iterator().next(), property.getTypeInformation()); + return entityReader.read(result.iterator().next(), property.getTypeInformation()); } private ReferenceCollection computeReferenceContext(MongoPersistentProperty property, Object value, @@ -107,6 +108,8 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop return ReferenceCollection.fromDBRef((DBRef) value); } + String collection = mappingContext.getRequiredPersistentEntity(property.getAssociationTargetType()).getCollection(); + if (value instanceof Document) { Document ref = (Document) value; @@ -120,12 +123,12 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop () -> ref.get("db", String.class)); String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, () -> ref.get("collection", - mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection())); + collection)); return new ReferenceCollection(targetDatabase, targetCollection); } return new ReferenceCollection(ref.getString("db"), ref.get("collection", - mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection())); + collection)); } if (property.isDocumentReference()) { @@ -135,16 +138,16 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop String targetDatabase = parseValueOrGet(documentReference.db(), bindingContext, () -> null); String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, - () -> mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection()); + () -> collection); return new ReferenceCollection(targetDatabase, targetCollection); } return new ReferenceCollection(null, - mappingContext.get().getPersistentEntity(property.getAssociationTargetType()).getCollection()); + collection); } - @Nullable + @SuppressWarnings("unchecked") private T parseValueOrGet(String value, ParameterBindingContext bindingContext, Supplier defaultValue) { if (!StringUtils.hasText(value)) { @@ -153,7 +156,7 @@ private T parseValueOrGet(String value, ParameterBindingContext bindingConte if (!BsonUtils.isJsonDocument(value) && value.contains("?#{")) { String s = "{ 'target-value' : " + value + "}"; - T evaluated = (T) codec.decode(s, bindingContext).get("target-value "); + T evaluated = (T) codec.decode(s, bindingContext).get("target-value"); return evaluated != null ? evaluated : defaultValue.get(); } @@ -186,6 +189,7 @@ EvaluationContext evaluationContextFor(MongoPersistentProperty property, Object return ctx; } + @SuppressWarnings("unchecked") DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object value, SpELContext spELContext) { DocumentReference documentReference = property.getDocumentReference(); @@ -196,7 +200,7 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object va if (property.isCollectionLike() && value instanceof Collection) { List ors = new ArrayList<>(); - for (Object entry : (Collection) value) { + for (Object entry : (Collection) value) { Document decoded = codec.decode(lookup, bindingContext(property, entry, spELContext)); ors.add(decoded); @@ -209,7 +213,7 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object va Map filterMap = new LinkedHashMap<>(); - for (Entry entry : ((Map) value).entrySet()) { + for (Entry entry : ((Map) value).entrySet()) { Document decoded = codec.decode(lookup, bindingContext(property, entry.getValue(), spELContext)); filterMap.put(entry.getKey(), decoded); @@ -321,9 +325,9 @@ public Document getSort() { int compareAgainstReferenceIndex(List referenceList, Document document1, Document document2) { - for (int i = 0; i < referenceList.size(); i++) { + for (Document document : referenceList) { - Set> entries = referenceList.get(i).entrySet(); + Set> entries = document.entrySet(); if (document1.entrySet().containsAll(entries)) { return -1; } @@ -334,4 +338,10 @@ int compareAgainstReferenceIndex(List referenceList, Document document return referenceList.size(); } } + + @FunctionalInterface + interface LookupFunction { + + Iterable apply(DocumentReferenceQuery referenceQuery, ReferenceCollection referenceCollection); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java index f29dc16a7c..dae2043b4b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java @@ -15,13 +15,10 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.Collections; - -import org.bson.Document; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import com.mongodb.DBRef; @@ -31,22 +28,8 @@ public interface ReferenceResolver { @Nullable - Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction); - - default Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, - ResultConversionFunction resultConversionFunction) { - - return resolveReference(property, source, referenceReader, (filter, ctx) -> { - if (property.isCollectionLike() || property.isMap()) { - return getReferenceLoader().bulkFetch(filter, ctx); - - } - - Object target = getReferenceLoader().fetch(filter, ctx); - return target == null ? Collections.emptyList() : Collections.singleton(getReferenceLoader().fetch(filter, ctx)); - }, resultConversionFunction); - } + Object resolveReference(MongoPersistentProperty property, Object source, + ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader); ReferenceLoader getReferenceLoader(); @@ -58,6 +41,8 @@ class ReferenceCollection { public ReferenceCollection(@Nullable String database, String collection) { + Assert.hasText(collection, "Collection must not be empty or null"); + this.database = database; this.collection = collection; } @@ -76,13 +61,9 @@ public String getDatabase() { } } - @FunctionalInterface - interface LookupFunction { - Iterable apply(DocumentReferenceQuery referenceQuery, ReferenceCollection referenceCollection); - } @FunctionalInterface - interface ResultConversionFunction { - Object apply(Object source, TypeInformation property); + interface MongoEntityReader { + Object read(Object source, TypeInformation property); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index b7b71a7fee..53af00fc54 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -47,7 +47,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope private static final Logger LOG = LoggerFactory.getLogger(BasicMongoPersistentProperty.class); - private static final String ID_FIELD_NAME = "_id"; + public static final String ID_FIELD_NAME = "_id"; private static final String LANGUAGE_FIELD_NAME = "language"; private static final Set> SUPPORTED_ID_TYPES = new HashSet>(); private static final Set SUPPORTED_ID_PROPERTY_NAMES = new HashSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java index f5d43c8ef0..91afb8c6ec 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java @@ -54,7 +54,8 @@ public static void assertProxyIsResolved(Object target, boolean expected) { public static void assertProxy(Object proxy, Consumer verification) { - LazyLoadingProxyGenerator.LazyLoadingInterceptor interceptor = (LazyLoadingProxyGenerator.LazyLoadingInterceptor) (proxy instanceof Advised ? ((Advised) proxy).getAdvisors()[0].getAdvice() + LazyLoadingProxyFactory.LazyLoadingInterceptor interceptor = (LazyLoadingProxyFactory.LazyLoadingInterceptor) (proxy instanceof Advised + ? ((Advised) proxy).getAdvisors()[0].getAdvice() : ((Factory) proxy).getCallback(0)); verification.accept(new LazyLoadingProxyValueRetriever(interceptor)); @@ -67,9 +68,9 @@ private static LazyLoadingInterceptor extractInterceptor(Object proxy) { public static class LazyLoadingProxyValueRetriever { - LazyLoadingProxyGenerator.LazyLoadingInterceptor interceptor; + LazyLoadingProxyFactory.LazyLoadingInterceptor interceptor; - public LazyLoadingProxyValueRetriever(LazyLoadingProxyGenerator.LazyLoadingInterceptor interceptor) { + public LazyLoadingProxyValueRetriever(LazyLoadingProxyFactory.LazyLoadingInterceptor interceptor) { this.interceptor = interceptor; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 9c157db759..d371b32c12 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1501,18 +1501,19 @@ static class WithDocumentReferences { SimpeEntityWithoutId noIdButLookupQuery; } - + + // TODO @Test void xxx() { - + Sample sample = new Sample(); sample.foo = "sample-id"; Query query = query(where("sample").is(sample)); - + org.bson.Document mappedObject = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDocumentReferences.class)); - + System.out.println("mappedObject.toJson(): " + mappedObject.toJson()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java index 28d5123502..9c898d28ce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java @@ -30,11 +30,10 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AliasFor; -import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.mapping.MappingException; -import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.data.spel.spi.EvaluationContextExtension; @@ -351,6 +350,9 @@ private static class DocumentWithComposedAnnotation {} @Document("#{myProperty}") class MappedWithExtension {} + @Document("${value.from.file}") + class MappedWithValue {} + @Document(collation = "#{myCollation}") class WithCollationFromSpEL {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java index b70930dae0..8a462a9370 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java @@ -18,20 +18,13 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; -import org.springframework.data.mongodb.core.convert.ReferenceLoader; -import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; -import org.springframework.data.mongodb.core.convert.ReferenceReader; -import org.springframework.data.util.TypeInformation; -import org.springframework.lang.Nullable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.text.DecimalFormat; import java.util.*; -import java.util.function.BiFunction; import java.util.regex.Pattern; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.bson.Document; import org.bson.types.ObjectId; @@ -48,12 +41,15 @@ import org.springframework.data.mongodb.core.convert.DbRefResolverCallback; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.ReferenceLoader; +import org.springframework.data.mongodb.core.convert.ReferenceLookupDelegate; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactory; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StopWatch; import org.springframework.util.StringUtils; @@ -106,7 +102,8 @@ public void setUp() throws Exception { @Nullable @Override - public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceReader referenceReader, LookupFunction lookupFunction, ResultConversionFunction resultConversionFunction) { + public Object resolveReference(MongoPersistentProperty property, Object source, + ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader) { return null; } From e96ef8e18f4e42c9afae34b7b503e0d95c43d169 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 19 May 2021 11:30:05 +0200 Subject: [PATCH 0428/1381] Avoid capturing lambdas, update javadoc and add tests. Also allow direct usage of (at)Reference from data commons to define associations. Original pull request: #3647. Closes #3602. --- .../convert/DefaultReferenceResolver.java | 69 +++--- .../core/convert/DocumentPointerFactory.java | 201 +++++++++++++----- .../core/convert/MappingMongoConverter.java | 45 ++-- .../MongoDatabaseFactoryReferenceLoader.java | 19 +- .../mongodb/core/convert/MongoWriter.java | 16 +- .../core/convert/NoOpDbRefResolver.java | 5 - .../mongodb/core/convert/QueryMapper.java | 5 +- .../mongodb/core/convert/ReferenceLoader.java | 62 ++++-- .../core/convert/ReferenceLookupDelegate.java | 182 ++++++++++++---- .../core/convert/ReferenceResolver.java | 60 +++++- .../data/mongodb/util/BsonUtils.java | 8 +- .../MongoTemplateDocumentReferenceTests.java | 105 ++++++++- .../DocumentPointerFactoryUnitTests.java | 139 ++++++++++++ .../MappingMongoConverterUnitTests.java | 10 +- .../performance/ReactivePerformanceTests.java | 4 - src/main/asciidoc/reference/mapping.adoc | 6 +- 16 files changed, 747 insertions(+), 189 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactoryUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java index 7e38b6995d..a678fd7da6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java @@ -19,40 +19,45 @@ import java.util.Collections; +import org.springframework.data.mongodb.core.mapping.DBRef; +import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; -import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** + * {@link ReferenceResolver} implementation that uses a given {@link ReferenceLookupDelegate} to load and convert entity + * associations expressed via a {@link MongoPersistentProperty persitent property}. Creates {@link LazyLoadingProxy + * proxies} for associations that should be lazily loaded. + * * @author Christoph Strobl */ public class DefaultReferenceResolver implements ReferenceResolver { private final ReferenceLoader referenceLoader; + private final LookupFunction collectionLookupFunction = (filter, ctx) -> getReferenceLoader().fetchMany(filter, ctx); + private final LookupFunction singleValueLookupFunction = (filter, ctx) -> { + Object target = getReferenceLoader().fetchOne(filter, ctx); + return target == null ? Collections.emptyList() : Collections.singleton(getReferenceLoader().fetchOne(filter, ctx)); + }; + + /** + * Create a new instance of {@link DefaultReferenceResolver}. + * + * @param referenceLoader must not be {@literal null}. + */ public DefaultReferenceResolver(ReferenceLoader referenceLoader) { + + Assert.notNull(referenceLoader, "ReferenceLoader must not be null!"); this.referenceLoader = referenceLoader; } - @Override - public ReferenceLoader getReferenceLoader() { - return referenceLoader; - } - - @Nullable @Override public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader) { - LookupFunction lookupFunction = (filter, ctx) -> { - if (property.isCollectionLike() || property.isMap()) { - return getReferenceLoader().fetchMany(filter, ctx); - - } - - Object target = getReferenceLoader().fetchOne(filter, ctx); - return target == null ? Collections.emptyList() - : Collections.singleton(getReferenceLoader().fetchOne(filter, ctx)); - }; + LookupFunction lookupFunction = (property.isCollectionLike() || property.isMap()) ? collectionLookupFunction + : singleValueLookupFunction; if (isLazyReference(property)) { return createLazyLoadingProxy(property, source, referenceLookupDelegate, lookupFunction, entityReader); @@ -61,13 +66,14 @@ public Object resolveReference(MongoPersistentProperty property, Object source, return referenceLookupDelegate.readReference(property, source, lookupFunction, entityReader); } - private Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, - ReferenceLookupDelegate referenceLookupDelegate, LookupFunction lookupFunction, - MongoEntityReader entityReader) { - return new LazyLoadingProxyFactory(referenceLookupDelegate).createLazyLoadingProxy(property, source, lookupFunction, - entityReader); - } - + /** + * Check if the association expressed by the given {@link MongoPersistentProperty property} should be resolved lazily. + * + * @param property + * @return return {@literal true} if the defined association is lazy. + * @see DBRef#lazy() + * @see DocumentReference#lazy() + */ protected boolean isLazyReference(MongoPersistentProperty property) { if (property.isDocumentReference()) { @@ -76,4 +82,19 @@ protected boolean isLazyReference(MongoPersistentProperty property) { return property.getDBRef() != null && property.getDBRef().lazy(); } + + /** + * The {@link ReferenceLoader} executing the lookup. + * + * @return never {@literal null}. + */ + protected ReferenceLoader getReferenceLoader() { + return referenceLoader; + } + + private Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, + ReferenceLookupDelegate referenceLookupDelegate, LookupFunction lookupFunction, MongoEntityReader entityReader) { + return new LazyLoadingProxyFactory(referenceLookupDelegate).createLazyLoadingProxy(property, source, lookupFunction, + entityReader); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java index 8e9554b6ba..09d69e4b27 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java @@ -15,18 +15,20 @@ */ package org.springframework.data.mongodb.core.convert; -import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.WeakHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bson.Document; - import org.springframework.core.convert.ConversionService; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.annotation.Reference; import org.springframework.data.mapping.PersistentPropertyAccessor; +import org.springframework.data.mapping.PersistentPropertyPath; +import org.springframework.data.mapping.PropertyPath; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.BeanWrapperPropertyAccessorFactory; import org.springframework.data.mongodb.core.mapping.DocumentPointer; @@ -34,6 +36,10 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; /** + * Internal API to construct {@link DocumentPointer} for a given property. Considers {@link LazyLoadingProxy}, + * registered {@link Object} to {@link DocumentPointer} {@link org.springframework.core.convert.converter.Converter}, + * simple {@literal _id} lookups and cases where the {@link DocumentPointer} needs to be computed via a lookup query. + * * @author Christoph Strobl * @since 3.3 */ @@ -41,17 +47,29 @@ class DocumentPointerFactory { private final ConversionService conversionService; private final MappingContext, MongoPersistentProperty> mappingContext; - private final Map linkageMap; - - public DocumentPointerFactory(ConversionService conversionService, + private final Map cache; + + /** + * A {@link Pattern} matching quoted and unquoted variants (with/out whitespaces) of + * {'_id' : ?#{#target} }. + */ + private static final Pattern DEFAULT_LOOKUP_PATTERN = Pattern.compile("\\{\\s?" + // document start (whitespace opt) + "['\"]?_id['\"]?" + // followed by an optionally quoted _id. Like: _id, '_id' or "_id" + "?\\s?:\\s?" + // then a colon optionally wrapped inside whitespaces + "['\"]?\\?#\\{#target\\}['\"]?" + // leading to the potentially quoted ?#{#target} expression + "\\s*}"); // some optional whitespaces and document close + + DocumentPointerFactory(ConversionService conversionService, MappingContext, MongoPersistentProperty> mappingContext) { this.conversionService = conversionService; this.mappingContext = mappingContext; - this.linkageMap = new HashMap<>(); + this.cache = new WeakHashMap<>(); } - public DocumentPointer computePointer(MongoPersistentProperty property, Object value, Class typeHint) { + DocumentPointer computePointer( + MappingContext, MongoPersistentProperty> mappingContext, + MongoPersistentProperty property, Object value, Class typeHint) { if (value instanceof LazyLoadingProxy) { return () -> ((LazyLoadingProxy) value).getSource(); @@ -59,92 +77,161 @@ public DocumentPointer computePointer(MongoPersistentProperty property, Objec if (conversionService.canConvert(typeHint, DocumentPointer.class)) { return conversionService.convert(value, DocumentPointer.class); - } else { + } - MongoPersistentEntity persistentEntity = mappingContext - .getRequiredPersistentEntity(property.getAssociationTargetType()); + MongoPersistentEntity persistentEntity = mappingContext + .getRequiredPersistentEntity(property.getAssociationTargetType()); - // TODO: Extract method - if (!property.getDocumentReference().lookup().toLowerCase(Locale.ROOT).replaceAll("\\s", "").replaceAll("'", "") - .equals("{_id:?#{#target}}")) { + if (usesDefaultLookup(property)) { + return () -> persistentEntity.getIdentifierAccessor(value).getIdentifier(); + } - MongoPersistentEntity valueEntity = mappingContext.getPersistentEntity(value.getClass()); - PersistentPropertyAccessor propertyAccessor; - if (valueEntity == null) { - propertyAccessor = BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(property.getOwner(), - value); - } else { - propertyAccessor = valueEntity.getPropertyAccessor(value); + MongoPersistentEntity valueEntity = mappingContext.getPersistentEntity(value.getClass()); + PersistentPropertyAccessor propertyAccessor; + if (valueEntity == null) { + propertyAccessor = BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(property.getOwner(), value); + } else { + propertyAccessor = valueEntity.getPropertyPathAccessor(value); + } - } + return cache.computeIfAbsent(property.getDocumentReference().lookup(), LinkageDocument::from) + .getDocumentPointer(mappingContext, persistentEntity, propertyAccessor); + } - return () -> linkageMap.computeIfAbsent(property.getDocumentReference().lookup(), LinkageDocument::new) - .get(persistentEntity, propertyAccessor); - } + private boolean usesDefaultLookup(MongoPersistentProperty property) { - // just take the id as a reference - return () -> persistentEntity.getIdentifierAccessor(value).getIdentifier(); + if (property.isDocumentReference()) { + return DEFAULT_LOOKUP_PATTERN.matcher(property.getDocumentReference().lookup()).matches(); + } + + Reference atReference = property.findAnnotation(Reference.class); + if (atReference != null) { + return true; } + + throw new IllegalStateException(String.format("%s does not seem to be define Reference", property)); } + /** + * Value object that computes a document pointer from a given lookup query by identifying SpEL expressions and + * inverting it. + * + *
      +	 * // source
      +	 * { 'firstname' : ?#{fn}, 'lastname' : '?#{ln} }
      +	 * 
      +	 * // target
      +	 * { 'fn' : ..., 'ln' : ... }
      +	 * 
      + * + * The actual pointer is the computed via + * {@link #getDocumentPointer(MappingContext, MongoPersistentEntity, PersistentPropertyAccessor)} applying values from + * the provided {@link PersistentPropertyAccessor} to the target document by looking at the keys of the expressions + * from the source. + */ static class LinkageDocument { - static final Pattern pattern = Pattern.compile("\\?#\\{#?[\\w\\d]*\\}"); + static final Pattern EXPRESSION_PATTERN = Pattern.compile("\\?#\\{#?(?[\\w\\d\\.\\-)]*)\\}"); + static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("###_(?\\d*)_###"); - String lookup; - org.bson.Document fetchDocument; - Map mapMap; + private final String lookup; + private final org.bson.Document documentPointer; + private final Map placeholderMap; - public LinkageDocument(String lookup) { + static LinkageDocument from(String lookup) { + return new LinkageDocument(lookup); + } - this.lookup = lookup; - String targetLookup = lookup; + private LinkageDocument(String lookup) { + this.lookup = lookup; + this.placeholderMap = new LinkedHashMap<>(); - Matcher matcher = pattern.matcher(lookup); int index = 0; - mapMap = new LinkedHashMap<>(); + Matcher matcher = EXPRESSION_PATTERN.matcher(lookup); + String targetLookup = lookup; - // TODO: Make explicit what's happening here while (matcher.find()) { - String expr = matcher.group(); - String sanitized = expr.substring(0, expr.length() - 1).replace("?#{#", "").replace("?#{", "") - .replace("target.", "").replaceAll("'", ""); - mapMap.put(index, sanitized); - targetLookup = targetLookup.replace(expr, index + ""); + String expression = matcher.group(); + String fieldName = matcher.group("fieldName").replace("target.", ""); + + String placeholder = placeholder(index); + placeholderMap.put(placeholder, fieldName); + targetLookup = targetLookup.replace(expression, "'" + placeholder + "'"); index++; } - fetchDocument = org.bson.Document.parse(targetLookup); + this.documentPointer = org.bson.Document.parse(targetLookup); } - org.bson.Document get(MongoPersistentEntity persistentEntity, PersistentPropertyAccessor propertyAccessor) { + private String placeholder(int index) { + return "###_" + index + "_###"; + } - org.bson.Document targetDocument = new Document(); + private boolean isPlaceholder(String key) { + return PLACEHOLDER_PATTERN.matcher(key).matches(); + } - // TODO: recursive matching over nested Documents or would the parameter binding json parser be a thing? - // like we have it ordered by index values and could provide the parameter array from it. + DocumentPointer getDocumentPointer( + MappingContext, MongoPersistentProperty> mappingContext, + MongoPersistentEntity persistentEntity, PersistentPropertyAccessor propertyAccessor) { + return () -> updatePlaceholders(documentPointer, new Document(), mappingContext, persistentEntity, + propertyAccessor); + } + + Document updatePlaceholders(org.bson.Document source, org.bson.Document target, + MappingContext, MongoPersistentProperty> mappingContext, + MongoPersistentEntity persistentEntity, PersistentPropertyAccessor propertyAccessor) { - for (Entry entry : fetchDocument.entrySet()) { + for (Entry entry : source.entrySet()) { + + if (entry.getKey().startsWith("$")) { + throw new InvalidDataAccessApiUsageException(String.format( + "Cannot derive document pointer from lookup '%s' using query operator (%s). Please consider registering a custom converter.", + lookup, entry.getKey())); + } - if (entry.getKey().equals("target")) { + if (entry.getValue() instanceof Document) { - String refKey = mapMap.get(entry.getValue()); + MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(entry.getKey()); + if (persistentProperty != null && persistentProperty.isEntity()) { - if (persistentEntity.hasIdProperty()) { - targetDocument.put(refKey, propertyAccessor.getProperty(persistentEntity.getIdProperty())); + MongoPersistentEntity nestedEntity = mappingContext.getPersistentEntity(persistentProperty.getType()); + target.put(entry.getKey(), updatePlaceholders((Document) entry.getValue(), new Document(), mappingContext, + nestedEntity, nestedEntity.getPropertyAccessor(propertyAccessor.getProperty(persistentProperty)))); } else { - targetDocument.put(refKey, propertyAccessor.getBean()); + target.put(entry.getKey(), updatePlaceholders((Document) entry.getValue(), new Document(), mappingContext, + persistentEntity, propertyAccessor)); } continue; } - Object target = propertyAccessor.getProperty(persistentEntity.getPersistentProperty(entry.getKey())); - String refKey = mapMap.get(entry.getValue()); - targetDocument.put(refKey, target); + if (placeholderMap.containsKey(entry.getValue())) { + + String attribute = placeholderMap.get(entry.getValue()); + if (attribute.contains(".")) { + attribute = attribute.substring(attribute.lastIndexOf('.') + 1); + } + + String fieldName = entry.getKey().equals("_id") ? "id" : entry.getKey(); + if (!fieldName.contains(".")) { + + Object targetValue = propertyAccessor.getProperty(persistentEntity.getPersistentProperty(fieldName)); + target.put(attribute, targetValue); + continue; + } + + PersistentPropertyPath path = mappingContext + .getPersistentPropertyPath(PropertyPath.from(fieldName, persistentEntity.getTypeInformation())); + Object targetValue = propertyAccessor.getProperty(path); + target.put(attribute, targetValue); + continue; + } + + target.put(entry.getKey(), entry.getValue()); } - return targetDocument; + return target; } } } 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 8a77b51e2f..87f0adeb62 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 @@ -45,6 +45,7 @@ import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.data.annotation.Reference; import org.springframework.data.convert.TypeMapper; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.MappingException; @@ -526,7 +527,7 @@ private void readAssociation(Association association, P return; } - if (property.isDocumentReference()) { + if (property.isDocumentReference() || (!property.isDbReference() && property.findAnnotation(Reference.class) != null)) { // quite unusual but sounds like worth having? @@ -587,43 +588,46 @@ public DBRef toDBRef(Object object, @Nullable MongoPersistentProperty referringP return createDBRef(object, referringProperty); } - public Object toDocumentReference(Object source, @Nullable MongoPersistentProperty referringProperty) { + @Override + public DocumentPointer toDocumentPointer(Object source, @Nullable MongoPersistentProperty referringProperty) { if (source instanceof LazyLoadingProxy) { - return ((LazyLoadingProxy) source).getSource(); + return () -> ((LazyLoadingProxy) source).getSource(); } - if (referringProperty != null) { + Assert.notNull(referringProperty, "Cannot create DocumentReference. The referringProperty must not be null!"); if (referringProperty.isDbReference()) { - return toDBRef(source, referringProperty); + return () -> toDBRef(source, referringProperty); } - if (referringProperty.isDocumentReference()) { + + if (referringProperty.isDocumentReference() || referringProperty.findAnnotation(Reference.class) != null) { return createDocumentPointer(source, referringProperty); } - } - throw new RuntimeException("oops - what's that " + source); + throw new IllegalArgumentException("The referringProperty is neither a DBRef nor a document reference"); } - Object createDocumentPointer(Object source, @Nullable MongoPersistentProperty referringProperty) { + DocumentPointer createDocumentPointer(Object source, @Nullable MongoPersistentProperty referringProperty) { if (referringProperty == null) { - return source; + return () -> source; + } + + if(source instanceof DocumentPointer) { + return (DocumentPointer) source; } if (ClassUtils.isAssignableValue(referringProperty.getType(), source) && conversionService.canConvert(referringProperty.getType(), DocumentPointer.class)) { - return conversionService.convert(source, DocumentPointer.class).getPointer(); + return conversionService.convert(source, DocumentPointer.class); } if (ClassUtils.isAssignableValue(referringProperty.getAssociationTargetType(), source)) { - return documentPointerFactory.computePointer(referringProperty, source, referringProperty.getActualType()) - .getPointer(); - + return documentPointerFactory.computePointer(mappingContext, referringProperty, source, referringProperty.getActualType()); } - return source; + return () -> source; } /** @@ -813,7 +817,7 @@ protected void writePropertyInternal(@Nullable Object obj, DocumentAccessor acce if (prop.isAssociation()) { accessor.put(prop, new DocumentPointerFactory(conversionService, mappingContext) - .computePointer(prop, obj, valueType.getType()).getPointer()); + .computePointer(mappingContext, prop, obj, valueType.getType()).getPointer()); return; } @@ -864,13 +868,14 @@ protected List createCollection(Collection collection, MongoPersisten return mappingContext.getPersistentEntity(property.getAssociationTargetType()).getIdentifierAccessor(it) .getIdentifier(); } - }).collect(Collectors.toList()), ClassTypeInformation.from(DocumentPointer.class), new BasicDBList()); + }).collect(Collectors.toList()), ClassTypeInformation.from(DocumentPointer.class), new ArrayList<>()); } if (property.hasExplicitWriteTarget()) { return writeCollectionInternal(collection, new FieldTypeInformation<>(property), new ArrayList<>()); } - return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList()); + + return writeCollectionInternal(collection, property.getTypeInformation(), new ArrayList<>()); } List dbList = new ArrayList<>(collection.size()); @@ -960,7 +965,7 @@ private List writeCollectionInternal(Collection source, @Nullable Typ collection.add(getPotentiallyConvertedSimpleWrite(element, componentType != null ? componentType.getType() : Object.class)); } else if (element instanceof Collection || elementType.isArray()) { - collection.add(writeCollectionInternal(BsonUtils.asCollection(element), componentType, new BasicDBList())); + collection.add(writeCollectionInternal(BsonUtils.asCollection(element), componentType, new ArrayList<>())); } else { Document document = new Document(); writeInternal(element, document, componentType); @@ -992,7 +997,7 @@ protected Bson writeMapInternal(Map obj, Bson bson, TypeInformat writeSimpleInternal(val, bson, simpleKey); } else if (val instanceof Collection || val.getClass().isArray()) { BsonUtils.addToMap(bson, simpleKey, - writeCollectionInternal(BsonUtils.asCollection(val), propertyType.getMapValueType(), new BasicDBList())); + writeCollectionInternal(BsonUtils.asCollection(val), propertyType.getMapValueType(), new ArrayList<>())); } else { Document document = new Document(); TypeInformation valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java index 2483f57543..0973e5a5fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java @@ -27,6 +27,9 @@ import com.mongodb.client.MongoCollection; /** + * {@link ReferenceLoader} implementation using a {@link MongoDatabaseFactory} to obtain raw {@link Document documents} + * for linked entities via a {@link ReferenceLoader.DocumentReferenceQuery}. + * * @author Christoph Strobl */ public class MongoDatabaseFactoryReferenceLoader implements ReferenceLoader { @@ -35,6 +38,9 @@ public class MongoDatabaseFactoryReferenceLoader implements ReferenceLoader { private final MongoDatabaseFactory mongoDbFactory; + /** + * @param mongoDbFactory must not be {@literal null}. + */ public MongoDatabaseFactoryReferenceLoader(MongoDatabaseFactory mongoDbFactory) { Assert.notNull(mongoDbFactory, "MongoDbFactory translator must not be null!"); @@ -43,20 +49,27 @@ public MongoDatabaseFactoryReferenceLoader(MongoDatabaseFactory mongoDbFactory) } @Override - public Iterable fetchMany(DocumentReferenceQuery filter, ReferenceCollection context) { + public Iterable fetchMany(DocumentReferenceQuery referenceQuery, ReferenceCollection context) { MongoCollection collection = getCollection(context); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Bulk fetching {} from {}.{}.", filter, + LOGGER.trace("Bulk fetching {} from {}.{}.", referenceQuery, StringUtils.hasText(context.getDatabase()) ? context.getDatabase() : collection.getNamespace().getDatabaseName(), context.getCollection()); } - return filter.apply(collection); + return referenceQuery.apply(collection); } + /** + * Obtain the {@link MongoCollection} for a given {@link ReferenceCollection} from the underlying + * {@link MongoDatabaseFactory}. + * + * @param context must not be {@literal null}. + * @return the {@link MongoCollection} targeted by the {@link ReferenceCollection}. + */ protected MongoCollection getCollection(ReferenceCollection context) { return MongoDatabaseUtils.getDatabase(context.getDatabase(), mongoDbFactory).getCollection(context.getCollection(), diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java index 779b3236d3..6bef57cb63 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java @@ -17,6 +17,8 @@ import org.bson.conversions.Bson; import org.springframework.data.convert.EntityWriter; +import org.springframework.data.mongodb.core.mapping.DocumentPointer; +import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.util.TypeInformation; @@ -61,6 +63,7 @@ default Object convertToMongoType(@Nullable Object obj) { default Object convertToMongoType(@Nullable Object obj, MongoPersistentEntity entity) { return convertToMongoType(obj, entity.getTypeInformation()); } + /** * Creates a {@link DBRef} to refer to the given object. * @@ -71,7 +74,16 @@ default Object convertToMongoType(@Nullable Object obj, MongoPersistentEntity */ DBRef toDBRef(Object object, @Nullable MongoPersistentProperty referingProperty); - default Object toDocumentReference(Object source, @Nullable MongoPersistentProperty referringProperty) { - return toDBRef(source, referringProperty); + /** + * Creates a the {@link DocumentPointer} representing the link to another entity. + * + * @param source the object to create a document link to. + * @param referringProperty the client-side property referring to the object which might carry additional metadata for + * the {@link DBRef} object to create. Can be {@literal null}. + * @return will never be {@literal null}. + * @since 3.3 + */ + default DocumentPointer toDocumentPointer(Object source, @Nullable MongoPersistentProperty referringProperty) { + return () -> toDBRef(source, referringProperty); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java index 41d7ab3c12..587d1a5047 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/NoOpDbRefResolver.java @@ -77,9 +77,4 @@ public Object resolveReference(MongoPersistentProperty property, Object source, ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader) { return null; } - - @Override - public ReferenceLoader getReferenceLoader() { - return handle(); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 36353e4f86..81c1c96ddf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -26,6 +26,7 @@ import org.bson.types.ObjectId; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; +import org.springframework.data.annotation.Reference; import org.springframework.data.domain.Example; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.MappingException; @@ -672,8 +673,8 @@ private Object createReferenceFor(Object source, MongoPersistentProperty propert return (DBRef) source; } - if(property != null && property.isDocumentReference()) { - return converter.toDocumentReference(source, property); + if(property != null && (property.isDocumentReference() || (!property.isDbReference() && property.findAnnotation(Reference.class) != null))) { + return converter.toDocumentPointer(source, property).getPointer(); } return converter.toDBRef(source, property); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java index 7cfd5e3153..2f96f57da2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java @@ -26,33 +26,70 @@ import com.mongodb.client.MongoCollection; /** + * The {@link ReferenceLoader} obtains raw {@link Document documents} for linked entities via a + * {@link ReferenceLoader.DocumentReferenceQuery}. + * * @author Christoph Strobl + * @since 3.3 */ public interface ReferenceLoader { + /** + * Obtain a single {@link Document} matching the given {@literal referenceQuery} in the {@literal context}. + * + * @param referenceQuery must not be {@literal null}. + * @param context must not be {@literal null}. + * @return the matching {@link Document} or {@literal null} if none found. + */ @Nullable - default Document fetchOne(DocumentReferenceQuery filter, ReferenceCollection context) { + default Document fetchOne(DocumentReferenceQuery referenceQuery, ReferenceCollection context) { - Iterator it = fetchMany(filter, context).iterator(); + Iterator it = fetchMany(referenceQuery, context).iterator(); return it.hasNext() ? it.next() : null; } - Iterable fetchMany(DocumentReferenceQuery filter, ReferenceCollection context); - + /** + * Obtain multiple {@link Document} matching the given {@literal referenceQuery} in the {@literal context}. + * + * @param referenceQuery must not be {@literal null}. + * @param context must not be {@literal null}. + * @return the matching {@link Document} or {@literal null} if none found. + */ + Iterable fetchMany(DocumentReferenceQuery referenceQuery, ReferenceCollection context); + + /** + * The {@link DocumentReferenceQuery} defines the criteria by which {@link Document documents} should be matched + * applying potentially given order criteria. + */ interface DocumentReferenceQuery { - Bson getFilter(); - + /** + * Get the query to obtain matching {@link Document documents}. + * + * @return never {@literal null}. + */ + Bson getQuery(); + + /** + * Get the sort criteria for ordering results. + * + * @return an empty {@link Document} by default. Never {@literal null}. + */ default Bson getSort() { return new Document(); } // TODO: Move apply method into something else that holds the collection and knows about single item/multi-item - // processing default Iterable apply(MongoCollection collection) { - return restoreOrder(collection.find(getFilter()).sort(getSort())); + return restoreOrder(collection.find(getQuery()).sort(getSort())); } + /** + * Restore the order of fetched documents. + * + * @param documents must not be {@literal null}. + * @return never {@literal null}. + */ default Iterable restoreOrder(Iterable documents) { return documents; } @@ -62,14 +99,14 @@ static DocumentReferenceQuery forSingleDocument(Bson bson) { return new DocumentReferenceQuery() { @Override - public Bson getFilter() { + public Bson getQuery() { return bson; } @Override public Iterable apply(MongoCollection collection) { - Document result = collection.find(getFilter()).sort(getSort()).limit(1).first(); + Document result = collection.find(getQuery()).sort(getSort()).limit(1).first(); return result != null ? Collections.singleton(result) : Collections.emptyList(); } }; @@ -80,16 +117,15 @@ static DocumentReferenceQuery forManyDocuments(Bson bson) { return new DocumentReferenceQuery() { @Override - public Bson getFilter() { + public Bson getQuery() { return bson; } @Override public Iterable apply(MongoCollection collection) { - return collection.find(getFilter()).sort(getSort()); + return collection.find(getQuery()).sort(getSort()); } }; } } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index 3c441c1388..09f4c1a8ae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.convert; +import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -29,7 +30,6 @@ import org.bson.Document; import org.bson.conversions.Bson; - import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.SpELContext; import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; @@ -64,6 +64,12 @@ public final class ReferenceLookupDelegate { private final SpELContext spELContext; private final ParameterBindingDocumentCodec codec; + /** + * Create a new {@link ReferenceLookupDelegate}. + * + * @param mappingContext must not be {@literal null}. + * @param spELContext must not be {@literal null}. + */ public ReferenceLookupDelegate( MappingContext, MongoPersistentProperty> mappingContext, SpELContext spELContext) { @@ -76,11 +82,20 @@ public ReferenceLookupDelegate( this.codec = new ParameterBindingDocumentCodec(); } + /** + * Read the reference expressed by the given property. + * + * @param property the reference defining property. Must not be {@literal null}. THe + * @param value the source value identifying to the referenced entity. Must not be {@literal null}. + * @param lookupFunction to execute a lookup query. Must not be {@literal null}. + * @param entityReader the callback to convert raw source values into actual domain types. Must not be + * {@literal null}. + * @return can be {@literal null}. + */ @Nullable - Object readReference(MongoPersistentProperty property, Object value, LookupFunction lookupFunction, + public Object readReference(MongoPersistentProperty property, Object value, LookupFunction lookupFunction, MongoEntityReader entityReader) { - DocumentReferenceQuery filter = computeFilter(property, value, spELContext); ReferenceCollection referenceCollection = computeReferenceContext(property, value, spELContext); @@ -100,10 +115,12 @@ Object readReference(MongoPersistentProperty property, Object value, LookupFunct private ReferenceCollection computeReferenceContext(MongoPersistentProperty property, Object value, SpELContext spELContext) { + // Use the first value as a reference for others in case of collection like if (value instanceof Iterable) { value = ((Iterable) value).iterator().next(); } + // handle DBRef value if (value instanceof DBRef) { return ReferenceCollection.fromDBRef((DBRef) value); } @@ -112,7 +129,7 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop if (value instanceof Document) { - Document ref = (Document) value; + Document documentPointer = (Document) value; if (property.isDocumentReference()) { @@ -120,15 +137,13 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop DocumentReference documentReference = property.getDocumentReference(); String targetDatabase = parseValueOrGet(documentReference.db(), bindingContext, - () -> ref.get("db", String.class)); + () -> documentPointer.get("db", String.class)); String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, - () -> ref.get("collection", - collection)); + () -> documentPointer.get("collection", collection)); return new ReferenceCollection(targetDatabase, targetCollection); } - return new ReferenceCollection(ref.getString("db"), ref.get("collection", - collection)); + return new ReferenceCollection(documentPointer.getString("db"), documentPointer.get("collection", collection)); } if (property.isDocumentReference()) { @@ -137,16 +152,24 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop DocumentReference documentReference = property.getDocumentReference(); String targetDatabase = parseValueOrGet(documentReference.db(), bindingContext, () -> null); - String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, - () -> collection); + String targetCollection = parseValueOrGet(documentReference.collection(), bindingContext, () -> collection); return new ReferenceCollection(targetDatabase, targetCollection); } - return new ReferenceCollection(null, - collection); + return new ReferenceCollection(null, collection); } + /** + * Use the given {@link ParameterBindingContext} to compute potential expressions against the value. + * + * @param value must not be {@literal null}. + * @param bindingContext must not be {@literal null}. + * @param defaultValue + * @param + * @return can be {@literal null}. + */ + @Nullable @SuppressWarnings("unchecked") private T parseValueOrGet(String value, ParameterBindingContext bindingContext, Supplier defaultValue) { @@ -154,12 +177,17 @@ private T parseValueOrGet(String value, ParameterBindingContext bindingConte return defaultValue.get(); } + // parameter binding requires a document, since we do not have one, construct it. if (!BsonUtils.isJsonDocument(value) && value.contains("?#{")) { String s = "{ 'target-value' : " + value + "}"; T evaluated = (T) codec.decode(s, bindingContext).get("target-value"); return evaluated != null ? evaluated : defaultValue.get(); } + if (BsonUtils.isJsonDocument(value)) { + return (T) codec.decode(value, bindingContext); + } + T evaluated = (T) bindingContext.evaluateExpression(value); return evaluated != null ? evaluated : defaultValue.get(); } @@ -171,8 +199,8 @@ ParameterBindingContext bindingContext(MongoPersistentProperty property, Object } ValueProvider valueProviderFor(Object source) { - return (index) -> { + return (index) -> { if (source instanceof Document) { return Streamable.of(((Document) source).values()).toList().get(index); } @@ -189,13 +217,24 @@ EvaluationContext evaluationContextFor(MongoPersistentProperty property, Object return ctx; } + /** + * Compute the query to retrieve linked documents. + * + * @param property must not be {@literal null}. + * @param value must not be {@literal null}. + * @param spELContext must not be {@literal null}. + * @return never {@literal null}. + */ @SuppressWarnings("unchecked") DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object value, SpELContext spELContext) { - DocumentReference documentReference = property.getDocumentReference(); + DocumentReference documentReference = property.isDocumentReference() ? property.getDocumentReference() + : ReferenceEmulatingDocumentReference.INSTANCE; + String lookup = documentReference.lookup(); - Document sort = parseValueOrGet(documentReference.sort(), bindingContext(property, value, spELContext), () -> null); + Document sort = parseValueOrGet(documentReference.sort(), bindingContext(property, value, spELContext), + () -> new Document()); if (property.isCollectionLike() && value instanceof Collection) { @@ -225,45 +264,94 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object va return new SingleDocumentReferenceQuery(codec.decode(lookup, bindingContext(property, value, spELContext)), sort); } + enum ReferenceEmulatingDocumentReference implements DocumentReference { + + INSTANCE; + + @Override + public Class annotationType() { + return DocumentReference.class; + } + + @Override + public String db() { + return ""; + } + + @Override + public String collection() { + return ""; + } + + @Override + public String lookup() { + return "{ '_id' : ?#{#target} }"; + } + + @Override + public String sort() { + return ""; + } + + @Override + public boolean lazy() { + return false; + } + } + + /** + * {@link DocumentReferenceQuery} implementation fetching a single {@link Document}. + */ static class SingleDocumentReferenceQuery implements DocumentReferenceQuery { - Document filter; - Document sort; + private final Document query; + private final Document sort; + + public SingleDocumentReferenceQuery(Document query, Document sort) { - public SingleDocumentReferenceQuery(Document filter, Document sort) { - this.filter = filter; + this.query = query; this.sort = sort; } @Override - public Bson getFilter() { - return filter; + public Bson getQuery() { + return query; + } + + @Override + public Document getSort() { + return sort; } @Override public Iterable apply(MongoCollection collection) { - Document result = collection.find(getFilter()).limit(1).first(); + Document result = collection.find(getQuery()).sort(getSort()).limit(1).first(); return result != null ? Collections.singleton(result) : Collections.emptyList(); } } + /** + * {@link DocumentReferenceQuery} implementation to retrieve linked {@link Document documents} stored inside a + * {@link Map} structure. Restores the original map order by matching individual query documents against the actual + * values. + */ static class MapDocumentReferenceQuery implements DocumentReferenceQuery { - private final Document filter; + private final Document query; private final Document sort; private final Map filterOrderMap; - public MapDocumentReferenceQuery(Document filter, Document sort, Map filterOrderMap) { + public MapDocumentReferenceQuery(Document query, Document sort, Map filterOrderMap) { - this.filter = filter; + this.query = query; this.sort = sort; this.filterOrderMap = filterOrderMap; } @Override - public Bson getFilter() { - return filter; + public Bson getQuery() { + return query; } @Override @@ -289,33 +377,38 @@ public Iterable restoreOrder(Iterable documents) { } } + /** + * {@link DocumentReferenceQuery} implementation to retrieve linked {@link Document documents} stored inside a + * {@link Collection} like structure. Restores the original order by matching individual query documents against the + * actual values. + */ static class ListDocumentReferenceQuery implements DocumentReferenceQuery { - private final Document filter; + private final Document query; private final Document sort; - public ListDocumentReferenceQuery(Document filter, Document sort) { + public ListDocumentReferenceQuery(Document query, Document sort) { - this.filter = filter; + this.query = query; this.sort = sort; } @Override public Iterable restoreOrder(Iterable documents) { - if (filter.containsKey("$or")) { - List ors = filter.get("$or", List.class); - List target = documents instanceof List ? (List) documents - : Streamable.of(documents).toList(); - return target.stream().sorted((o1, o2) -> compareAgainstReferenceIndex(ors, o1, o2)) - .collect(Collectors.toList()); + List target = documents instanceof List ? (List) documents + : Streamable.of(documents).toList(); + + if (!sort.isEmpty() || !query.containsKey("$or")) { + return target; } - return documents; + List ors = query.get("$or", List.class); + return target.stream().sorted((o1, o2) -> compareAgainstReferenceIndex(ors, o1, o2)).collect(Collectors.toList()); } - public Document getFilter() { - return filter; + public Document getQuery() { + return query; } @Override @@ -339,9 +432,18 @@ int compareAgainstReferenceIndex(List referenceList, Document document } } + /** + * The function that can execute a given {@link DocumentReferenceQuery} within the {@link ReferenceCollection} to + * obtain raw results. + */ @FunctionalInterface interface LookupFunction { + /** + * @param referenceQuery never {@literal null}. + * @param referenceCollection never {@literal null}. + * @return never {@literal null}. + */ Iterable apply(DocumentReferenceQuery referenceQuery, ReferenceCollection referenceCollection); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java index dae2043b4b..91235b5270 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.convert; +import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; @@ -23,47 +24,92 @@ import com.mongodb.DBRef; /** + * The {@link ReferenceResolver} allows to load and convert linked entities. + * * @author Christoph Strobl */ public interface ReferenceResolver { + /** + * Resolve the association defined via the given property from a given source value. May deliver a + * {@link LazyLoadingProxy proxy instance} in case of a lazy loading association. + * + * @param property the association defining property. + * @param source the association source value. + * @param referenceLookupDelegate the lookup executing component. + * @param entityReader conversion function capable of constructing entities from raw source. + * @return can be {@literal null}. + */ @Nullable Object resolveReference(MongoPersistentProperty property, Object source, ReferenceLookupDelegate referenceLookupDelegate, MongoEntityReader entityReader); - ReferenceLoader getReferenceLoader(); - + /** + * {@link ReferenceCollection} is a value object that contains information about the target database and collection + * name of an association. + */ class ReferenceCollection { - @Nullable + @Nullable // private final String database; private final String collection; + /** + * @param database can be {@literal null} to indicate the configured default + * {@link MongoDatabaseFactory#getMongoDatabase() database} should be used. + * @param collection the target collection name. Must not be {@literal null}. + */ public ReferenceCollection(@Nullable String database, String collection) { - Assert.hasText(collection, "Collection must not be empty or null"); + Assert.hasText(collection, "Collection must not be empty or null!"); this.database = database; this.collection = collection; } - static ReferenceCollection fromDBRef(DBRef dbRef) { + /** + * Create a new instance of {@link ReferenceCollection} from the given {@link DBRef}. + * + * @param dbRef must not be {@literal null}. + * @return new instance of {@link ReferenceCollection}. + */ + public static ReferenceCollection fromDBRef(DBRef dbRef) { return new ReferenceCollection(dbRef.getDatabaseName(), dbRef.getCollectionName()); } + /** + * Get the target collection name. + * + * @return never {@literal null}. + */ public String getCollection() { return collection; } + /** + * Get the target database name. If {@literal null} the default database should be used. + * + * @return can be {@literal null}. + */ @Nullable public String getDatabase() { return database; } } - + /** + * Domain type conversion callback interface that allows to read + */ @FunctionalInterface interface MongoEntityReader { - Object read(Object source, TypeInformation property); + + /** + * Read values from the given source into an object defined via the given {@link TypeInformation}. + * + * @param source never {@literal null}. + * @param typeInformation information abount the desired target type. + * @return never {@literal null}. + */ + Object read(Object source, TypeInformation typeInformation); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index f4bd9436e7..4d51af7dee 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -349,7 +349,13 @@ public static String toJson(@Nullable Document source) { * @since 3.0 */ public static boolean isJsonDocument(@Nullable String value) { - return StringUtils.hasText(value) && (value.startsWith("{") && value.endsWith("}")); + + if(!StringUtils.hasText(value)) { + return false; + } + + String potentialJson = value.trim(); + return potentialJson.startsWith("{") && potentialJson.endsWith("}"); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index 593e1cd3cf..2c1caf316a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -38,6 +38,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Reference; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils; import org.springframework.data.mongodb.core.mapping.DocumentPointer; @@ -380,6 +381,33 @@ void readCollectionObjectReferenceFromDocumentDeclaringCollectionName() { new ObjectRefOfDocumentWithEmbeddedCollectionName("ref-1", "me-the-1-referenced-object")); } + @Test // GH-3602 + void useOrderFromAnnotatedSort() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + String refCollectionName = template.getCollectionName(SimpleObjectRef.class); + Document refSource1 = new Document("_id", "ref-1").append("value", "me-the-1-referenced-object"); + Document refSource2 = new Document("_id", "ref-2").append("value", "me-the-2-referenced-object"); + Document refSource3 = new Document("_id", "ref-3").append("value", "me-the-3-referenced-object"); + Document source = new Document("_id", "id-1").append("value", "v1").append("simpleSortedValueRef", + Arrays.asList("ref-1", "ref-3", "ref-2")); + + template.execute(db -> { + + db.getCollection(refCollectionName).insertOne(refSource1); + db.getCollection(refCollectionName).insertOne(refSource2); + db.getCollection(refCollectionName).insertOne(refSource3); + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.getSimpleSortedValueRef()).containsExactly( + new SimpleObjectRef("ref-3", "me-the-3-referenced-object"), + new SimpleObjectRef("ref-2", "me-the-2-referenced-object"), + new SimpleObjectRef("ref-1", "me-the-1-referenced-object")); + } + @Test // GH-3602 void readObjectReferenceFromDocumentNotRelatingToTheIdProperty() { @@ -857,7 +885,8 @@ void updateDerivedMappingFromLookup() { template.save(book); - template.update(Book.class).matching(where("id").is(book.id)).apply(new Update().set("publisher", publisher)).first(); + template.update(Book.class).matching(where("id").is(book.id)).apply(new Update().set("publisher", publisher)) + .first(); Document target = template.execute(db -> { return db.getCollection(template.getCollectionName(Book.class)).find(Filters.eq("_id", book.id)).first(); @@ -890,6 +919,56 @@ void queryDerivedMappingFromLookup() { assertThat(result.publisher).isNotNull(); } + @Test // GH-3602 + void allowsDirectUsageOfAtReference() { + + Publisher publisher = new Publisher(); + publisher.id = "p-1"; + publisher.acronym = "TOR"; + publisher.name = "Tom Doherty Associates"; + + template.save(publisher); + + UsingAtReference root = new UsingAtReference(); + root.id = "book-1"; + root.publisher = publisher; + + template.save(root); + + Document target = template.execute(db -> { + return db.getCollection(template.getCollectionName(UsingAtReference.class)).find(Filters.eq("_id", root.id)).first(); + }); + + assertThat(target).containsEntry("publisher", "p-1"); + + UsingAtReference result = template.findOne(query(where("id").is(root.id)), UsingAtReference.class); + assertThat(result.publisher).isNotNull(); + } + + @Test // GH-3602 + void updateWhenUsingAtReferenceDirectly() { + + Publisher publisher = new Publisher(); + publisher.id = "p-1"; + publisher.acronym = "TOR"; + publisher.name = "Tom Doherty Associates"; + + template.save(publisher); + + UsingAtReference root = new UsingAtReference(); + root.id = "book-1"; + + template.save(root); + template.update(UsingAtReference.class).matching(where("id").is(root.id)).apply(new Update().set("publisher", publisher)).first(); + + Document target = template.execute(db -> { + return db.getCollection(template.getCollectionName(UsingAtReference.class)).find(Filters.eq("_id", root.id)).first(); + }); + + assertThat(target).containsEntry("publisher", "p-1"); + + } + @Data static class SingleRefRoot { @@ -930,6 +1009,9 @@ static class CollectionRefRoot { @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") // List simpleValueRef; + @DocumentReference(lookup = "{ '_id' : '?#{#target}' }", sort = "{ '_id' : -1 } ") // + List simpleSortedValueRef; + @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") // Map mapValueRef; @@ -1051,7 +1133,8 @@ public DocumentPointer convert(SimpleObjectRefWithReadingConverter sou static class WithRefA/* to B */ implements ReferenceAble { @Id String id; - @DocumentReference WithRefB toB; + @DocumentReference // + WithRefB toB; @Override public Object toReference() { @@ -1065,9 +1148,11 @@ public Object toReference() { static class WithRefB/* to A */ implements ReferenceAble { @Id String id; - @DocumentReference(lazy = true) WithRefA lazyToA; + @DocumentReference(lazy = true) // + WithRefA lazyToA; - @DocumentReference WithRefA eagerToA; + @DocumentReference // + WithRefA eagerToA; @Override public Object toReference() { @@ -1091,7 +1176,8 @@ static class Book { String id; - @DocumentReference(lookup = "{ 'acronym' : ?#{acc}, 'name' : ?#{n} }") Publisher publisher; + @DocumentReference(lookup = "{ 'acronym' : ?#{acc}, 'name' : ?#{n} }") // + Publisher publisher; } @@ -1102,4 +1188,13 @@ static class Publisher { String name; } + @Data + static class UsingAtReference { + + String id; + + @Reference // + Publisher publisher; + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactoryUnitTests.java new file mode 100644 index 0000000000..6990ddfe88 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactoryUnitTests.java @@ -0,0 +1,139 @@ +/* + * Copyright 2021 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 + * + * https://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.convert; + +import static org.assertj.core.api.Assertions.*; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.mongodb.core.convert.DocumentPointerFactory.LinkageDocument; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; + +/** + * @author Christoph Strobl + */ +public class DocumentPointerFactoryUnitTests { + + @Test // GH-3602 + void errorsOnMongoOperatorUsage() { + + LinkageDocument source = LinkageDocument.from("{ '_id' : { '$eq' : 1 } }"); + + assertThatExceptionOfType(InvalidDataAccessApiUsageException.class) + .isThrownBy(() -> getPointerValue(source, new Book())) // + .withMessageContaining("$eq"); + } + + @Test // GH-3602 + void computesStaticPointer() { + + LinkageDocument source = LinkageDocument.from("{ '_id' : 1 }"); + + assertThat(getPointerValue(source, new Book())).isEqualTo(new Document("_id", 1)); + } + + @Test // GH-3602 + void computesPointerWithIdValuePlaceholder() { + + LinkageDocument source = LinkageDocument.from("{ '_id' : ?#{id} }"); + + assertThat(getPointerValue(source, new Book("book-1", null, null))).isEqualTo(new Document("id", "book-1")); + } + + @Test // GH-3602 + void computesPointerForNonIdValuePlaceholder() { + + LinkageDocument source = LinkageDocument.from("{ 'title' : ?#{book_title} }"); + + assertThat(getPointerValue(source, new Book("book-1", "Living With A Seal", null))) + .isEqualTo(new Document("book_title", "Living With A Seal")); + } + + @Test // GH-3602 + void computesPlaceholderFromNestedPathValue() { + + LinkageDocument source = LinkageDocument.from("{ 'metadata.pages' : ?#{p} } }"); + + assertThat(getPointerValue(source, new Book("book-1", "Living With A Seal", null, new Metadata(272)))) + .isEqualTo(new Document("p", 272)); + } + + @Test // GH-3602 + void computesNestedPlaceholderPathValue() { + + LinkageDocument source = LinkageDocument.from("{ 'metadata' : { 'pages' : ?#{metadata.pages} } }"); + + assertThat(getPointerValue(source, new Book("book-1", "Living With A Seal", null, new Metadata(272)))) + .isEqualTo(new Document("metadata", new Document("pages", 272))); + } + + Object getPointerValue(LinkageDocument linkageDocument, Object value) { + + MongoMappingContext mappingContext = new MongoMappingContext(); + MongoPersistentEntity persistentEntity = mappingContext.getPersistentEntity(value.getClass()); + return linkageDocument + .getDocumentPointer(mappingContext, persistentEntity, persistentEntity.getPropertyPathAccessor(value)) + .getPointer(); + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + static class Book { + String id; + String title; + List author; + Metadata metadata; + + public Book(String id, String title, List author) { + this.id = id; + this.title = title; + this.author = author; + } + } + + static class Metadata { + + int pages; + + public Metadata(int pages) { + this.pages = pages; + } + + public int getPages() { + return pages; + } + + public void setPages(int pages) { + this.pages = pages; + } + } + + @Data + static class Author { + String id; + String firstname; + String lastname; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index a3836fd8b3..bd3e98788f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -580,9 +580,9 @@ void writesMapsOfObjectsCorrectly() { org.bson.Document map = (org.bson.Document) field; Object foo = map.get("Foo"); - assertThat(foo).isInstanceOf(BasicDBList.class); + assertThat(foo).isInstanceOf(List.class); - BasicDBList value = (BasicDBList) foo; + List value = (List) foo; assertThat(value.size()).isEqualTo(1); assertThat(value.get(0)).isEqualTo("Bar"); } @@ -695,9 +695,9 @@ void writesPlainMapOfCollectionsCorrectly() { assertThat(result.containsKey("Foo")).isTrue(); assertThat(result.get("Foo")).isNotNull(); - assertThat(result.get("Foo")).isInstanceOf(BasicDBList.class); + assertThat(result.get("Foo")).isInstanceOf(List.class); - BasicDBList list = (BasicDBList) result.get("Foo"); + List list = (List) result.get("Foo"); assertThat(list.size()).isEqualTo(1); assertThat(list.get(0)).isEqualTo(Locale.US.toString()); @@ -744,7 +744,7 @@ void writesArraysAsMapValuesCorrectly() { org.bson.Document map = (org.bson.Document) mapObject; Object valueObject = map.get("foo"); - assertThat(valueObject).isInstanceOf(BasicDBList.class); + assertThat(valueObject).isInstanceOf(List.class); List list = (List) valueObject; assertThat(list.size()).isEqualTo(1); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java index 8a462a9370..be9335f2eb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/ReactivePerformanceTests.java @@ -129,10 +129,6 @@ public List bulkFetch(List dbRefs) { return null; } - @Override - public ReferenceLoader getReferenceLoader() { - return null; - } }, context); operations = new ReactiveMongoTemplate(mongoDbFactory, converter); diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 1998fe1ad8..9f9a461ee6 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -902,6 +902,10 @@ It is possible to alter resolution defaults (listed below) via the attributes of | The single document lookup query evaluating placeholders via SpEL expressions using `#target` as the marker for a given source value. `Collection` like or `Map` properties combine individual lookups via an `$or` operator. | An `_id` field based query (`{ '_id' : ?#{#target} }`) using the loaded source value. +| `sort` +| Used for sorting result documents on server side. +| None by default. Result order of `Collection` like properties is restored based on the used lookup query. + | `lazy` | If set to `true` value resolution is delayed upon first access of the property. | Resolves properties eagerly by default. @@ -1182,7 +1186,7 @@ We know it is tempting to use all kinds of MongoDB query operators in the lookup * Mind that resolution takes time and consider a lazy strategy. * A collection of document references is bulk loaded using an `$or` operator. + The original element order is restored in memory which cannot be done when using MongoDB query operators. -In this case Results will be ordered as they are received from the store. +In this case Results will be ordered as they are received from the store or via the provided `@DocumentReference(sort = ...)` attribute. And a few more general remarks: From 5ab75eb65aada8c3989b99b2441810e2e16204a0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 21 May 2021 10:55:59 +0200 Subject: [PATCH 0429/1381] Polishing. Reduce dependencies in tests by using NoOpDbRefResolver. Add since tags. Tweak documentation. Extract entity references into own documentation fragment. Original pull request: #3647. Closes #3602. --- .../core/convert/MappingMongoConverter.java | 2 - .../MongoDatabaseFactoryReferenceLoader.java | 3 +- .../mongodb/core/convert/ReferenceLoader.java | 3 +- .../core/convert/ReferenceLookupDelegate.java | 1 + .../mongodb/core/mapping/DocumentPointer.java | 5 +- .../core/mapping/DocumentReference.java | 64 +-- .../MongoTransactionManagerUnitTests.java | 28 +- .../mongodb/core/CountQueryUnitTests.java | 33 +- .../MongoTemplateDocumentReferenceTests.java | 8 +- .../FilterExpressionUnitTests.java | 5 +- .../convert/CustomConvertersUnitTests.java | 3 +- .../convert/MappingMongoConverterTests.java | 26 +- .../convert/MongoExampleMapperUnitTests.java | 70 ++- .../core/convert/QueryMapperUnitTests.java | 22 +- .../core/convert/UpdateMapperUnitTests.java | 4 +- .../query/AbstractMongoQueryUnitTests.java | 5 +- .../ConvertingParameterAccessorUnitTests.java | 22 +- .../query/MongoQueryCreatorUnitTests.java | 120 ++--- .../query/PartTreeMongoQueryUnitTests.java | 38 +- .../src/test/resources/logback.xml | 1 - src/main/asciidoc/new-features.adoc | 2 +- .../reference/document-references.adoc | 440 ++++++++++++++++++ src/main/asciidoc/reference/mapping.adoc | 429 +---------------- 23 files changed, 680 insertions(+), 654 deletions(-) create mode 100644 src/main/asciidoc/reference/document-references.adoc 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 87f0adeb62..413ce2ce44 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 @@ -546,8 +546,6 @@ private void readAssociation(Association association, P DBRef dbref = value instanceof DBRef ? (DBRef) value : null; - // TODO: accessor.setProperty(property, dbRefResolver.resolveReference(property, value, referenceReader, - // context::convert)); accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java index 0973e5a5fb..d68af1fb5a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoDatabaseFactoryReferenceLoader.java @@ -29,8 +29,9 @@ /** * {@link ReferenceLoader} implementation using a {@link MongoDatabaseFactory} to obtain raw {@link Document documents} * for linked entities via a {@link ReferenceLoader.DocumentReferenceQuery}. - * + * * @author Christoph Strobl + * @since 3.3 */ public class MongoDatabaseFactoryReferenceLoader implements ReferenceLoader { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java index 2f96f57da2..70a0f43c0f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLoader.java @@ -28,7 +28,7 @@ /** * The {@link ReferenceLoader} obtains raw {@link Document documents} for linked entities via a * {@link ReferenceLoader.DocumentReferenceQuery}. - * + * * @author Christoph Strobl * @since 3.3 */ @@ -79,7 +79,6 @@ default Bson getSort() { return new Document(); } - // TODO: Move apply method into something else that holds the collection and knows about single item/multi-item default Iterable apply(MongoCollection collection) { return restoreOrder(collection.find(getQuery()).sort(getSort())); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index 09f4c1a8ae..616abb325e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -57,6 +57,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @since 3.3 */ public final class ReferenceLookupDelegate { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java index de7fbff866..3b432a8c12 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentPointer.java @@ -17,8 +17,9 @@ /** * A custom pointer to a linked document to be used along with {@link DocumentReference} for storing the linkage value. - * + * * @author Christoph Strobl + * @since 3.3 */ @FunctionalInterface public interface DocumentPointer { @@ -27,7 +28,7 @@ public interface DocumentPointer { * The actual pointer value. This can be any simple type, like a {@link String} or {@link org.bson.types.ObjectId} or * a {@link org.bson.Document} holding more information like the target collection, multiple fields forming the key, * etc. - * + * * @return the value stored in MongoDB and used for constructing the {@link DocumentReference#lookup() lookup query}. */ T getPointer(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java index 0846c4022c..6fd5e96877 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/DocumentReference.java @@ -22,13 +22,14 @@ import java.lang.annotation.Target; import org.springframework.data.annotation.Reference; +import org.springframework.data.mongodb.MongoDatabaseFactory; /** - * A {@link DocumentReference} offers an alternative way of linking entities in MongoDB. While the goal is the same as - * when using {@link DBRef}, the store representation is different and can be literally anything, a single value, an - * entire {@link org.bson.Document}, basically everything that can be stored in MongoDB. By default, the mapping layer - * will use the referenced entities {@literal id} value for storage and retrieval. - * + * A {@link DocumentReference} allows referencing entities in MongoDB using a flexible schema. While the goal is the + * same as when using {@link DBRef}, the store representation is different. The reference can be anything, a single + * value, an entire {@link org.bson.Document}, basically everything that can be stored in MongoDB. By default, the + * mapping layer will use the referenced entities {@literal id} value for storage and retrieval. + * *
        * public class Account {
        *   private String id;
      @@ -40,7 +41,7 @@
        *   @DocumentReference
        *   private List<Account> accounts;
        * }
      - * 
      + *
        * Account account = ...
        *
        * mongoTemplate.insert(account);
      @@ -50,43 +51,41 @@
        *   .apply(new Update().push("accounts").value(account))
        *   .first();
        * 
      - * - * {@link #lookup()} allows to define custom queries that are independent from the {@literal id} field and in - * combination with {@link org.springframework.data.convert.WritingConverter writing converters} offer a flexible way of - * defining links between entities. - * + * + * {@link #lookup()} allows defining a query filter that is independent from the {@literal _id} field and in combination + * with {@link org.springframework.data.convert.WritingConverter writing converters} offers a flexible way of defining + * references between entities. + * *
        * public class Book {
      - * 	 private ObjectId id;
      - * 	 private String title;
      + * 	private ObjectId id;
      + * 	private String title;
        *
      - * 	 @Field("publisher_ac")
      - * 	 @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }")
      - * 	 private Publisher publisher;
      + * 	@Field("publisher_ac") @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") private Publisher publisher;
        * }
        *
        * public class Publisher {
        *
      - * 	 private ObjectId id;
      - * 	 private String acronym;
      - * 	 private String name;
      + * 	private ObjectId id;
      + * 	private String acronym;
      + * 	private String name;
        *
      - * 	 @DocumentReference(lazy = true)
      - * 	 private List<Book> books;
      + * 	@DocumentReference(lazy = true) private List<Book> books;
        * }
        *
        * @WritingConverter
        * public class PublisherReferenceConverter implements Converter<Publisher, DocumentPointer<String>> {
        *
      - *    public DocumentPointer<String> convert(Publisher source) {
      + * 	public DocumentPointer<String> convert(Publisher source) {
        * 		return () -> source.getAcronym();
      - *    }
      + * 	}
        * }
        * 
      * * @author Christoph Strobl * @since 3.3 - * @see MongoDB Reference Documentation + * @see MongoDB + * Reference Documentation */ @Documented @Retention(RetentionPolicy.RUNTIME) @@ -95,22 +94,25 @@ public @interface DocumentReference { /** - * The database the linked entity resides in. + * The database the referenced entity resides in. Uses the default database provided by + * {@link org.springframework.data.mongodb.MongoDatabaseFactory} if empty. * - * @return empty String by default. Uses the default database provided buy the {@link org.springframework.data.mongodb.MongoDatabaseFactory}. + * @see MongoDatabaseFactory#getMongoDatabase() + * @see MongoDatabaseFactory#getMongoDatabase(String) */ String db() default ""; /** - * The database the linked entity resides in. + * The collection the referenced entity resides in. Defaults to the collection of the referenced entity type. * - * @return empty String by default. Uses the property type for collection resolution. + * @see MongoPersistentEntity#getCollection() */ String collection() default ""; /** - * The single document lookup query. In case of an {@link java.util.Collection} or {@link java.util.Map} property - * the individual lookups are combined via an `$or` operator. + * The single document lookup query. In case of an {@link java.util.Collection} or {@link java.util.Map} property the + * individual lookups are combined via an {@code $or} operator. {@code target} points to the source value (or + * document) stored at the reference property. Properties of {@code target} can be used to define the reference query. * * @return an {@literal _id} based lookup. */ @@ -118,8 +120,6 @@ /** * A specific sort. - * - * @return empty String by default. */ String sort() default ""; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java index dfb48fdbb1..bb05a283b2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java @@ -25,6 +25,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; @@ -37,12 +38,15 @@ import com.mongodb.client.ClientSession; import com.mongodb.client.MongoDatabase; import com.mongodb.session.ServerSession; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; /** * @author Christoph Strobl */ @ExtendWith(MockitoExtension.class) -public class MongoTransactionManagerUnitTests { +@MockitoSettings(strictness = Strictness.LENIENT) +class MongoTransactionManagerUnitTests { @Mock ClientSession session; @Mock ClientSession session2; @@ -53,23 +57,25 @@ public class MongoTransactionManagerUnitTests { @Mock MongoDatabase db2; @BeforeEach - public void setUp() { + void setUp() { when(dbFactory.getSession(any())).thenReturn(session, session2); + when(dbFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); + when(dbFactory2.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); when(dbFactory.withSession(session)).thenReturn(dbFactory); when(dbFactory.getMongoDatabase()).thenReturn(db); when(session.getServerSession()).thenReturn(serverSession); } @AfterEach - public void verifyTransactionSynchronizationManager() { + void verifyTransactionSynchronizationManager() { assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty()).isTrue(); assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isFalse(); } @Test // DATAMONGO-1920 - public void triggerCommitCorrectly() { + void triggerCommitCorrectly() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionStatus txStatus = txManager.getTransaction(new DefaultTransactionDefinition()); @@ -91,7 +97,7 @@ public void triggerCommitCorrectly() { } @Test // DATAMONGO-1920 - public void participateInOnGoingTransactionWithCommit() { + void participateInOnGoingTransactionWithCommit() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionStatus txStatus = txManager.getTransaction(new DefaultTransactionDefinition()); @@ -126,7 +132,7 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { } @Test // DATAMONGO-1920 - public void participateInOnGoingTransactionWithRollbackOnly() { + void participateInOnGoingTransactionWithRollbackOnly() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionStatus txStatus = txManager.getTransaction(new DefaultTransactionDefinition()); @@ -163,7 +169,7 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { } @Test // DATAMONGO-1920 - public void triggerRollbackCorrectly() { + void triggerRollbackCorrectly() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionStatus txStatus = txManager.getTransaction(new DefaultTransactionDefinition()); @@ -185,7 +191,7 @@ public void triggerRollbackCorrectly() { } @Test // DATAMONGO-1920 - public void suspendTransactionWhilePropagationNotSupported() { + void suspendTransactionWhilePropagationNotSupported() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); TransactionStatus txStatus = txManager.getTransaction(new DefaultTransactionDefinition()); @@ -228,7 +234,7 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { } @Test // DATAMONGO-1920 - public void suspendTransactionWhilePropagationRequiresNew() { + void suspendTransactionWhilePropagationRequiresNew() { when(dbFactory.withSession(session2)).thenReturn(dbFactory2); when(dbFactory2.getMongoDatabase()).thenReturn(db2); @@ -277,7 +283,7 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { } @Test // DATAMONGO-1920 - public void readonlyShouldInitiateASessionStartAndCommitTransaction() { + void readonlyShouldInitiateASessionStartAndCommitTransaction() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); @@ -303,7 +309,7 @@ public void readonlyShouldInitiateASessionStartAndCommitTransaction() { } @Test // DATAMONGO-1920 - public void readonlyShouldInitiateASessionStartAndRollbackTransaction() { + void readonlyShouldInitiateASessionStartAndRollbackTransaction() { MongoTransactionManager txManager = new MongoTransactionManager(dbFactory); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java index 4b5ed6f2a8..dcb35a7d4b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CountQueryUnitTests.java @@ -27,6 +27,7 @@ import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -39,27 +40,25 @@ * @author Mark Paluch * @author Christoph Strobl */ -public class CountQueryUnitTests { +class CountQueryUnitTests { - QueryMapper mapper; - MongoMappingContext context; - MappingMongoConverter converter; - - MongoDatabaseFactory factory = mock(MongoDatabaseFactory.class); + private QueryMapper mapper; + private MongoMappingContext context; + private MappingMongoConverter converter; @BeforeEach - public void setUp() { + void setUp() { this.context = new MongoMappingContext(); - this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); this.converter.afterPropertiesSet(); this.mapper = new QueryMapper(converter); } @Test // DATAMONGO-2059 - public void nearToGeoWithinWithoutDistance() { + void nearToGeoWithinWithoutDistance() { Query source = query(where("location").near(new Point(-73.99171, 40.738868))); org.bson.Document target = postProcessQueryForCount(source); @@ -69,7 +68,7 @@ public void nearToGeoWithinWithoutDistance() { } @Test // DATAMONGO-2059 - public void nearAndExisting$and() { + void nearAndExisting$and() { Query source = query(where("location").near(new Point(-73.99171, 40.738868)).minDistance(0.01)) .addCriteria(new Criteria().andOperator(where("foo").is("bar"))); @@ -83,7 +82,7 @@ public void nearToGeoWithinWithoutDistance() { } @Test // DATAMONGO-2059 - public void nearSphereToGeoWithinWithoutDistance() { + void nearSphereToGeoWithinWithoutDistance() { Query source = query(where("location").nearSphere(new Point(-73.99171, 40.738868))); org.bson.Document target = postProcessQueryForCount(source); @@ -93,7 +92,7 @@ public void nearSphereToGeoWithinWithoutDistance() { } @Test // DATAMONGO-2059 - public void nearToGeoWithinWithMaxDistance() { + void nearToGeoWithinWithMaxDistance() { Query source = query(where("location").near(new Point(-73.99171, 40.738868)).maxDistance(10)); org.bson.Document target = postProcessQueryForCount(source); @@ -103,7 +102,7 @@ public void nearToGeoWithinWithMaxDistance() { } @Test // DATAMONGO-2059 - public void nearSphereToGeoWithinWithMaxDistance() { + void nearSphereToGeoWithinWithMaxDistance() { Query source = query(where("location").nearSphere(new Point(-73.99171, 40.738868)).maxDistance(10)); org.bson.Document target = postProcessQueryForCount(source); @@ -113,7 +112,7 @@ public void nearSphereToGeoWithinWithMaxDistance() { } @Test // DATAMONGO-2059 - public void nearToGeoWithinWithMinDistance() { + void nearToGeoWithinWithMinDistance() { Query source = query(where("location").near(new Point(-73.99171, 40.738868)).minDistance(0.01)); org.bson.Document target = postProcessQueryForCount(source); @@ -124,7 +123,7 @@ public void nearToGeoWithinWithMinDistance() { } @Test // DATAMONGO-2059 - public void nearToGeoWithinWithMaxDistanceAndCombinedWithOtherCriteria() { + void nearToGeoWithinWithMaxDistanceAndCombinedWithOtherCriteria() { Query source = query( where("name").is("food").and("location").near(new Point(-73.99171, 40.738868)).maxDistance(10)); @@ -135,7 +134,7 @@ public void nearToGeoWithinWithMaxDistanceAndCombinedWithOtherCriteria() { } @Test // DATAMONGO-2059 - public void nearToGeoWithinWithMinDistanceOrCombinedWithOtherCriteria() { + void nearToGeoWithinWithMinDistanceOrCombinedWithOtherCriteria() { Query source = query(new Criteria().orOperator(where("name").is("food"), where("location").near(new Point(-73.99171, 40.738868)).minDistance(0.01))); @@ -146,7 +145,7 @@ public void nearToGeoWithinWithMinDistanceOrCombinedWithOtherCriteria() { } @Test // DATAMONGO-2059 - public void nearToGeoWithinWithMaxDistanceOrCombinedWithOtherCriteria() { + void nearToGeoWithinWithMaxDistanceOrCombinedWithOtherCriteria() { Query source = query(new Criteria().orOperator(where("name").is("food"), where("location").near(new Point(-73.99171, 40.738868)).maxDistance(10))); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index 2c1caf316a..fa1deb4f1c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -1094,17 +1094,17 @@ public Object toReference() { } } - static class ReferencableConverter implements Converter { + static class ReferencableConverter implements Converter> { @Nullable @Override - public DocumentPointer convert(ReferenceAble source) { + public DocumentPointer convert(ReferenceAble source) { return source::toReference; } } @WritingConverter - class DocumentToSimpleObjectRefWithReadingConverter + static class DocumentToSimpleObjectRefWithReadingConverter implements Converter, SimpleObjectRefWithReadingConverter> { @Nullable @@ -1118,7 +1118,7 @@ public SimpleObjectRefWithReadingConverter convert(DocumentPointer sou } @WritingConverter - class SimpleObjectRefWithReadingConverterToDocumentConverter + static class SimpleObjectRefWithReadingConverterToDocumentConverter implements Converter> { @Nullable diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java index 1580b4efb0..a318a5559b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/FilterExpressionUnitTests.java @@ -32,6 +32,7 @@ import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -41,8 +42,6 @@ @ExtendWith(MockitoExtension.class) class FilterExpressionUnitTests { - @Mock MongoDatabaseFactory mongoDbFactory; - private AggregationOperationContext aggregationContext; private MongoMappingContext mappingContext; @@ -51,7 +50,7 @@ void setUp() { mappingContext = new MongoMappingContext(); aggregationContext = new TypeBasedAggregationOperationContext(Sales.class, mappingContext, - new QueryMapper(new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), mappingContext))); + new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext))); } @Test // DATAMONGO-1491 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java index 1c1ba0715d..67b51f1140 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java @@ -49,7 +49,6 @@ class CustomConvertersUnitTests { @Mock BarToDocumentConverter barToDocumentConverter; @Mock DocumentToBarConverter documentToBarConverter; - @Mock MongoDatabaseFactory mongoDbFactory; private MongoMappingContext context; @@ -67,7 +66,7 @@ void setUp() { context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); context.initialize(); - converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context); + converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); converter.setCustomConversions(conversions); converter.afterPropertiesSet(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index 66c2cc9822..2b17ed4b06 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -59,18 +59,18 @@ @ExtendWith(MongoClientExtension.class) public class MappingMongoConverterTests { - public static final String DATABASE = "mapping-converter-tests"; + private static final String DATABASE = "mapping-converter-tests"; - static @Client MongoClient client; + private static @Client MongoClient client; - MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); + private MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); - MappingMongoConverter converter; - MongoMappingContext mappingContext; - DbRefResolver dbRefResolver; + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; + private DbRefResolver dbRefResolver; @BeforeEach - public void setUp() { + void setUp() { MongoDatabase database = client.getDatabase(DATABASE); @@ -90,7 +90,7 @@ public void setUp() { } @Test // DATAMONGO-2004 - public void resolvesLazyDBRefOnAccess() { + void resolvesLazyDBRefOnAccess() { client.getDatabase(DATABASE).getCollection("samples") .insertMany(Arrays.asList(new Document("_id", "sample-1").append("value", "one"), @@ -102,7 +102,6 @@ public void resolvesLazyDBRefOnAccess() { WithLazyDBRef target = converter.read(WithLazyDBRef.class, source); verify(dbRefResolver).resolveDbRef(any(), isNull(), any(), any()); - verifyNoMoreInteractions(dbRefResolver); assertThat(target.lazyList).isInstanceOf(LazyLoadingProxy.class); assertThat(target.getLazyList()).contains(new Sample("sample-1", "one"), new Sample("sample-2", "two")); @@ -111,7 +110,7 @@ public void resolvesLazyDBRefOnAccess() { } @Test // DATAMONGO-2004 - public void resolvesLazyDBRefConstructorArgOnAccess() { + void resolvesLazyDBRefConstructorArgOnAccess() { client.getDatabase(DATABASE).getCollection("samples") .insertMany(Arrays.asList(new Document("_id", "sample-1").append("value", "one"), @@ -123,7 +122,6 @@ public void resolvesLazyDBRefConstructorArgOnAccess() { WithLazyDBRefAsConstructorArg target = converter.read(WithLazyDBRefAsConstructorArg.class, source); verify(dbRefResolver).resolveDbRef(any(), isNull(), any(), any()); - verifyNoMoreInteractions(dbRefResolver); assertThat(target.lazyList).isInstanceOf(LazyLoadingProxy.class); assertThat(target.getLazyList()).contains(new Sample("sample-1", "one"), new Sample("sample-2", "two")); @@ -132,7 +130,7 @@ public void resolvesLazyDBRefConstructorArgOnAccess() { } @Test // DATAMONGO-2400 - public void readJavaTimeValuesWrittenViaCodec() { + void readJavaTimeValuesWrittenViaCodec() { configureConverterWithNativeJavaTimeCodec(); MongoCollection mongoCollection = client.getDatabase(DATABASE).getCollection("java-time-types"); @@ -160,7 +158,7 @@ public static class WithLazyDBRef { @Id String id; @DBRef(lazy = true) List lazyList; - public List getLazyList() { + List getLazyList() { return lazyList; } } @@ -176,7 +174,7 @@ public WithLazyDBRefAsConstructorArg(String id, List lazyList) { this.lazyList = lazyList; } - public List getLazyList() { + List getLazyList() { return lazyList; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java index ef92b8ff0c..796eecc7f7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java @@ -54,27 +54,25 @@ * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) -public class MongoExampleMapperUnitTests { +class MongoExampleMapperUnitTests { - MongoExampleMapper mapper; - MongoMappingContext context; - MappingMongoConverter converter; - - @Mock MongoDatabaseFactory factory; + private MongoExampleMapper mapper; + private MongoMappingContext context; + private MappingMongoConverter converter; @BeforeEach - public void setUp() { + void setUp() { this.context = new MongoMappingContext(); - this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); this.converter.afterPropertiesSet(); this.mapper = new MongoExampleMapper(converter); } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsSet() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsSet() { FlatDocument probe = new FlatDocument(); probe.id = "steelheart"; @@ -84,7 +82,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsSet() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenMultipleValuesSet() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenMultipleValuesSet() { FlatDocument probe = new FlatDocument(); probe.id = "steelheart"; @@ -98,7 +96,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenMultipleValuesSet() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsNotSet() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsNotSet() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -110,7 +108,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsNotSet() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenListHasValues() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenListHasValues() { FlatDocument probe = new FlatDocument(); probe.listOfString = Arrays.asList("Prof", "Tia", "David"); @@ -122,7 +120,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenListHasValues() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenFieldNameIsCustomized() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenFieldNameIsCustomized() { FlatDocument probe = new FlatDocument(); probe.customNamedField = "Mitosis"; @@ -132,7 +130,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenFieldNameIsCustomized() } @Test // DATAMONGO-1245 - public void typedExampleShouldContainTypeRestriction() { + void typedExampleShouldContainTypeRestriction() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); @@ -146,7 +144,7 @@ public void typedExampleShouldContainTypeRestriction() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedAsFlatMapWhenGivenNestedElementsWithLenientMatchMode() { + void exampleShouldBeMappedAsFlatMapWhenGivenNestedElementsWithLenientMatchMode() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); @@ -157,7 +155,7 @@ public void exampleShouldBeMappedAsFlatMapWhenGivenNestedElementsWithLenientMatc } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedAsExactObjectWhenGivenNestedElementsWithStrictMatchMode() { + void exampleShouldBeMappedAsExactObjectWhenGivenNestedElementsWithStrictMatchMode() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); @@ -170,7 +168,7 @@ public void exampleShouldBeMappedAsExactObjectWhenGivenNestedElementsWithStrictM } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsStarting() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsStarting() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -184,7 +182,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsStarti } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeContainingDotsWhenStringMatchModeIsStarting() { + void exampleShouldBeMappedCorrectlyForFlatTypeContainingDotsWhenStringMatchModeIsStarting() { FlatDocument probe = new FlatDocument(); probe.stringValue = "fire.ight"; @@ -198,7 +196,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeContainingDotsWhenStringMat } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsEnding() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsEnding() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -212,7 +210,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsEnding } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeRegex() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeRegex() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -226,7 +224,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeRegex() } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabledAndMatchModeSet() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabledAndMatchModeSet() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -240,7 +238,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabledAndMat } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabled() { + void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabled() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -255,7 +253,7 @@ public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabled() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedWhenContainingDBRef() { + void exampleShouldBeMappedWhenContainingDBRef() { FlatDocument probe = new FlatDocument(); probe.stringValue = "steelheart"; @@ -271,7 +269,7 @@ public void exampleShouldBeMappedWhenContainingDBRef() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedWhenDBRefIsNull() { + void exampleShouldBeMappedWhenDBRefIsNull() { FlatDocument probe = new FlatDocument(); probe.stringValue = "steelheart"; @@ -283,7 +281,7 @@ public void exampleShouldBeMappedWhenDBRefIsNull() { } @Test // DATAMONGO-1245 - public void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() { + void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() { ClassWithGeoTypes probe = new ClassWithGeoTypes(); probe.legacyPoint = new Point(10D, 20D); @@ -296,7 +294,7 @@ public void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() { } @Test // DATAMONGO-1245 - public void mappingShouldExcludeFieldWithCustomNameCorrectly() { + void mappingShouldExcludeFieldWithCustomNameCorrectly() { FlatDocument probe = new FlatDocument(); probe.customNamedField = "foo"; @@ -311,7 +309,7 @@ public void mappingShouldExcludeFieldWithCustomNameCorrectly() { } @Test // DATAMONGO-1245 - public void mappingShouldExcludeFieldCorrectly() { + void mappingShouldExcludeFieldCorrectly() { FlatDocument probe = new FlatDocument(); probe.customNamedField = "foo"; @@ -326,7 +324,7 @@ public void mappingShouldExcludeFieldCorrectly() { } @Test // DATAMONGO-1245 - public void mappingShouldExcludeNestedFieldCorrectly() { + void mappingShouldExcludeNestedFieldCorrectly() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); @@ -342,7 +340,7 @@ public void mappingShouldExcludeNestedFieldCorrectly() { } @Test // DATAMONGO-1245 - public void mappingShouldExcludeNestedFieldWithCustomNameCorrectly() { + void mappingShouldExcludeNestedFieldWithCustomNameCorrectly() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); @@ -358,7 +356,7 @@ public void mappingShouldExcludeNestedFieldWithCustomNameCorrectly() { } @Test // DATAMONGO-1245 - public void mappingShouldFavorFieldSpecificationStringMatcherOverDefaultStringMatcher() { + void mappingShouldFavorFieldSpecificationStringMatcherOverDefaultStringMatcher() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -372,7 +370,7 @@ public void mappingShouldFavorFieldSpecificationStringMatcherOverDefaultStringMa } @Test // DATAMONGO-1245 - public void mappingShouldIncludePropertiesFromHierarchicalDocument() { + void mappingShouldIncludePropertiesFromHierarchicalDocument() { HierachicalDocument probe = new HierachicalDocument(); probe.stringValue = "firefight"; @@ -386,7 +384,7 @@ public void mappingShouldIncludePropertiesFromHierarchicalDocument() { } @Test // DATAMONGO-1459 - public void mapsAnyMatchingExampleCorrectly() { + void mapsAnyMatchingExampleCorrectly() { FlatDocument probe = new FlatDocument(); probe.stringValue = "firefight"; @@ -398,7 +396,7 @@ public void mapsAnyMatchingExampleCorrectly() { } @Test // DATAMONGO-1768 - public void allowIgnoringTypeRestrictionBySettingUpTypeKeyAsAnIgnoredPath() { + void allowIgnoringTypeRestrictionBySettingUpTypeKeyAsAnIgnoredPath() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); @@ -411,13 +409,13 @@ public void allowIgnoringTypeRestrictionBySettingUpTypeKeyAsAnIgnoredPath() { } @Test // DATAMONGO-1768 - public void allowIgnoringTypeRestrictionBySettingUpTypeKeyAsAnIgnoredPathWhenUsingCustomTypeMapper() { + void allowIgnoringTypeRestrictionBySettingUpTypeKeyAsAnIgnoredPathWhenUsingCustomTypeMapper() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); probe.flatDoc.stringValue = "conflux"; - MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper() { @Override @@ -445,7 +443,7 @@ public void writeType(TypeInformation info, Bson sink) { } @Test // DATAMONGO-1768 - public void untypedExampleShouldNotInferTypeRestriction() { + void untypedExampleShouldNotInferTypeRestriction() { WrapperDocument probe = new WrapperDocument(); probe.flatDoc = new FlatDocument(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index d371b32c12..f7b5ec76d7 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -34,14 +34,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.geo.Point; -import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; @@ -80,14 +79,12 @@ public class QueryMapperUnitTests { private MongoMappingContext context; private MappingMongoConverter converter; - @Mock MongoDatabaseFactory factory; - @BeforeEach void beforeEach() { this.context = new MongoMappingContext(); - this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); this.converter.afterPropertiesSet(); this.mapper = new QueryMapper(converter); @@ -1502,19 +1499,4 @@ static class WithDocumentReferences { } - // TODO - @Test - void xxx() { - - Sample sample = new Sample(); - sample.foo = "sample-id"; - - Query query = query(where("sample").is(sample)); - - org.bson.Document mappedObject = mapper.getMappedObject(query.getQueryObject(), - context.getPersistentEntity(WithDocumentReferences.class)); - - System.out.println("mappedObject.toJson(): " + mappedObject.toJson()); - } - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index f5b5493327..a8d5f12b9f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -48,6 +48,7 @@ import org.springframework.data.mapping.MappingException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.Unwrapped; @@ -70,7 +71,6 @@ @ExtendWith(MockitoExtension.class) class UpdateMapperUnitTests { - @Mock MongoDatabaseFactory factory; private MappingMongoConverter converter; private MongoMappingContext context; private UpdateMapper mapper; @@ -88,7 +88,7 @@ void setUp() { this.context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); this.context.initialize(); - this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); this.converter.setCustomConversions(conversions); this.converter.afterPropertiesSet(); 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 c2803b6124..92c99185eb 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 @@ -45,6 +45,7 @@ import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.convert.DbRefResolver; @@ -93,7 +94,9 @@ void setUp() { doReturn(persitentEntityMock).when(mappingContextMock).getRequiredPersistentEntity(Mockito.any(Class.class)); doReturn(Person.class).when(persitentEntityMock).getType(); - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDatabaseFactory.class)); + MongoDatabaseFactory mongoDbFactory = mock(MongoDatabaseFactory.class); + when(mongoDbFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory); MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContextMock); converter.afterPropertiesSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java index 87994bcbec..1624f40d77 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java @@ -28,6 +28,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -46,35 +47,36 @@ * @author Christoph Strobl */ @ExtendWith(MockitoExtension.class) -public class ConvertingParameterAccessorUnitTests { +class ConvertingParameterAccessorUnitTests { @Mock MongoDatabaseFactory factory; @Mock MongoParameterAccessor accessor; - MongoMappingContext context; - MappingMongoConverter converter; - DbRefResolver resolver; + private MongoMappingContext context; + private MappingMongoConverter converter; + private DbRefResolver resolver; @BeforeEach - public void setUp() { + void setUp() { + when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); this.context = new MongoMappingContext(); this.resolver = new DefaultDbRefResolver(factory); this.converter = new MappingMongoConverter(resolver, context); } @Test - public void rejectsNullDbRefResolver() { + void rejectsNullDbRefResolver() { assertThatIllegalArgumentException().isThrownBy(() -> new MappingMongoConverter((DbRefResolver) null, context)); } @Test - public void rejectsNullContext() { + void rejectsNullContext() { assertThatIllegalArgumentException().isThrownBy(() -> new MappingMongoConverter(resolver, null)); } @Test - public void convertsCollectionUponAccess() { + void convertsCollectionUponAccess() { when(accessor.getBindableValue(0)).thenReturn(Arrays.asList("Foo")); @@ -88,7 +90,7 @@ public void convertsCollectionUponAccess() { } @Test // DATAMONGO-505 - public void convertsAssociationsToDBRef() { + void convertsAssociationsToDBRef() { Property property = new Property(); property.id = 5L; @@ -102,7 +104,7 @@ public void convertsAssociationsToDBRef() { } @Test // DATAMONGO-505 - public void convertsAssociationsToDBRefForCollections() { + void convertsAssociationsToDBRefForCollections() { Property property = new Property(); property.id = 5L; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index 12446f7e0f..02d4b7bc09 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -38,12 +38,14 @@ import org.springframework.data.geo.Shape; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.Venue; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.geo.GeoJsonLineString; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; @@ -67,22 +69,20 @@ * @author Thomas Darimont * @author Christoph Strobl */ -public class MongoQueryCreatorUnitTests { +class MongoQueryCreatorUnitTests { - MappingContext, MongoPersistentProperty> context; - MongoConverter converter; + private MappingContext, MongoPersistentProperty> context; + private MongoConverter converter; @BeforeEach - public void beforeEach() { + void beforeEach() { context = new MongoMappingContext(); - - DbRefResolver resolver = new DefaultDbRefResolver(mock(MongoDatabaseFactory.class)); - converter = new MappingMongoConverter(resolver, context); + converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); } @Test - public void createsQueryCorrectly() { + void createsQueryCorrectly() { PartTree tree = new PartTree("findByFirstName", Person.class); @@ -92,7 +92,7 @@ public void createsQueryCorrectly() { } @Test // DATAMONGO-469 - public void createsAndQueryCorrectly() { + void createsAndQueryCorrectly() { Person person = new Person(); MongoQueryCreator creator = new MongoQueryCreator(new PartTree("findByFirstNameAndFriend", Person.class), @@ -103,7 +103,7 @@ public void createsAndQueryCorrectly() { } @Test - public void createsNotNullQueryCorrectly() { + void createsNotNullQueryCorrectly() { PartTree tree = new PartTree("findByFirstNameNotNull", Person.class); Query query = new MongoQueryCreator(tree, getAccessor(converter), context).createQuery(); @@ -112,7 +112,7 @@ public void createsNotNullQueryCorrectly() { } @Test - public void createsIsNullQueryCorrectly() { + void createsIsNullQueryCorrectly() { PartTree tree = new PartTree("findByFirstNameIsNull", Person.class); Query query = new MongoQueryCreator(tree, getAccessor(converter), context).createQuery(); @@ -121,7 +121,7 @@ public void createsIsNullQueryCorrectly() { } @Test - public void bindsMetricDistanceParameterToNearSphereCorrectly() throws Exception { + void bindsMetricDistanceParameterToNearSphereCorrectly() throws Exception { Point point = new Point(10, 20); Distance distance = new Distance(2.5, Metrics.KILOMETERS); @@ -132,7 +132,7 @@ public void bindsMetricDistanceParameterToNearSphereCorrectly() throws Exception } @Test - public void bindsDistanceParameterToNearCorrectly() throws Exception { + void bindsDistanceParameterToNearCorrectly() throws Exception { Point point = new Point(10, 20); Distance distance = new Distance(2.5); @@ -143,7 +143,7 @@ public void bindsDistanceParameterToNearCorrectly() throws Exception { } @Test - public void createsLessThanEqualQueryCorrectly() { + void createsLessThanEqualQueryCorrectly() { PartTree tree = new PartTree("findByAgeLessThanEqual", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, 18), context); @@ -153,7 +153,7 @@ public void createsLessThanEqualQueryCorrectly() { } @Test - public void createsGreaterThanEqualQueryCorrectly() { + void createsGreaterThanEqualQueryCorrectly() { PartTree tree = new PartTree("findByAgeGreaterThanEqual", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, 18), context); @@ -163,7 +163,7 @@ public void createsGreaterThanEqualQueryCorrectly() { } @Test // DATAMONGO-338 - public void createsExistsClauseCorrectly() { + void createsExistsClauseCorrectly() { PartTree tree = new PartTree("findByAgeExists", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, true), context); @@ -172,7 +172,7 @@ public void createsExistsClauseCorrectly() { } @Test // DATAMONGO-338 - public void createsRegexClauseCorrectly() { + void createsRegexClauseCorrectly() { PartTree tree = new PartTree("findByFirstNameRegex", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, ".*"), context); @@ -181,7 +181,7 @@ public void createsRegexClauseCorrectly() { } @Test // DATAMONGO-338 - public void createsTrueClauseCorrectly() { + void createsTrueClauseCorrectly() { PartTree tree = new PartTree("findByActiveTrue", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter), context); @@ -190,7 +190,7 @@ public void createsTrueClauseCorrectly() { } @Test // DATAMONGO-338 - public void createsFalseClauseCorrectly() { + void createsFalseClauseCorrectly() { PartTree tree = new PartTree("findByActiveFalse", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter), context); @@ -199,7 +199,7 @@ public void createsFalseClauseCorrectly() { } @Test // DATAMONGO-413 - public void createsOrQueryCorrectly() { + void createsOrQueryCorrectly() { PartTree tree = new PartTree("findByFirstNameOrAge", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "Dave", 42), context); @@ -209,7 +209,7 @@ public void createsOrQueryCorrectly() { } @Test // DATAMONGO-347 - public void createsQueryReferencingADBRefCorrectly() { + void createsQueryReferencingADBRefCorrectly() { User user = new User(); user.id = new ObjectId(); @@ -222,7 +222,7 @@ public void createsQueryReferencingADBRefCorrectly() { } @Test // DATAMONGO-418 - public void createsQueryWithStartingWithPredicateCorrectly() { + void createsQueryWithStartingWithPredicateCorrectly() { PartTree tree = new PartTree("findByUsernameStartingWith", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "Matt"), context); @@ -232,7 +232,7 @@ public void createsQueryWithStartingWithPredicateCorrectly() { } @Test // DATAMONGO-418 - public void createsQueryWithEndingWithPredicateCorrectly() { + void createsQueryWithEndingWithPredicateCorrectly() { PartTree tree = new PartTree("findByUsernameEndingWith", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "ews"), context); @@ -242,7 +242,7 @@ public void createsQueryWithEndingWithPredicateCorrectly() { } @Test // DATAMONGO-418 - public void createsQueryWithContainingPredicateCorrectly() { + void createsQueryWithContainingPredicateCorrectly() { PartTree tree = new PartTree("findByUsernameContaining", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "thew"), context); @@ -268,7 +268,7 @@ private void assertBindsDistanceToQuery(Point point, Distance distance, Query re } @Test // DATAMONGO-770 - public void createsQueryWithFindByIgnoreCaseCorrectly() { + void createsQueryWithFindByIgnoreCaseCorrectly() { PartTree tree = new PartTree("findByfirstNameIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -278,7 +278,7 @@ public void createsQueryWithFindByIgnoreCaseCorrectly() { } @Test // DATAMONGO-770 - public void createsQueryWithFindByNotIgnoreCaseCorrectly() { + void createsQueryWithFindByNotIgnoreCaseCorrectly() { PartTree tree = new PartTree("findByFirstNameNotIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -288,7 +288,7 @@ public void createsQueryWithFindByNotIgnoreCaseCorrectly() { } @Test // DATAMONGO-770 - public void createsQueryWithFindByStartingWithIgnoreCaseCorrectly() { + void createsQueryWithFindByStartingWithIgnoreCaseCorrectly() { PartTree tree = new PartTree("findByFirstNameStartingWithIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -298,7 +298,7 @@ public void createsQueryWithFindByStartingWithIgnoreCaseCorrectly() { } @Test // DATAMONGO-770 - public void createsQueryWithFindByEndingWithIgnoreCaseCorrectly() { + void createsQueryWithFindByEndingWithIgnoreCaseCorrectly() { PartTree tree = new PartTree("findByFirstNameEndingWithIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -308,7 +308,7 @@ public void createsQueryWithFindByEndingWithIgnoreCaseCorrectly() { } @Test // DATAMONGO-770 - public void createsQueryWithFindByContainingIgnoreCaseCorrectly() { + void createsQueryWithFindByContainingIgnoreCaseCorrectly() { PartTree tree = new PartTree("findByFirstNameContainingIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -318,7 +318,7 @@ public void createsQueryWithFindByContainingIgnoreCaseCorrectly() { } @Test // DATAMONGO-770 - public void shouldThrowExceptionForQueryWithFindByIgnoreCaseOnNonStringProperty() { + void shouldThrowExceptionForQueryWithFindByIgnoreCaseOnNonStringProperty() { PartTree tree = new PartTree("findByFirstNameAndAgeIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "foo", 42), context); @@ -328,7 +328,7 @@ public void shouldThrowExceptionForQueryWithFindByIgnoreCaseOnNonStringProperty( } @Test // DATAMONGO-770 - public void shouldOnlyGenerateLikeExpressionsForStringPropertiesIfAllIgnoreCase() { + void shouldOnlyGenerateLikeExpressionsForStringPropertiesIfAllIgnoreCase() { PartTree tree = new PartTree("findByFirstNameAndAgeAllIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave", 42), context); @@ -338,7 +338,7 @@ public void shouldOnlyGenerateLikeExpressionsForStringPropertiesIfAllIgnoreCase( } @Test // DATAMONGO-566 - public void shouldCreateDeleteByQueryCorrectly() { + void shouldCreateDeleteByQueryCorrectly() { PartTree tree = new PartTree("deleteByFirstName", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave", 42), context); @@ -350,7 +350,7 @@ public void shouldCreateDeleteByQueryCorrectly() { } @Test // DATAMONGO-566 - public void shouldCreateDeleteByQueryCorrectlyForMultipleCriteriaAndCaseExpressions() { + void shouldCreateDeleteByQueryCorrectlyForMultipleCriteriaAndCaseExpressions() { PartTree tree = new PartTree("deleteByFirstNameAndAgeAllIgnoreCase", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave", 42), context); @@ -362,7 +362,7 @@ public void shouldCreateDeleteByQueryCorrectlyForMultipleCriteriaAndCaseExpressi } @Test // DATAMONGO-1075 - public void shouldCreateInClauseWhenUsingContainsOnCollectionLikeProperty() { + void shouldCreateInClauseWhenUsingContainsOnCollectionLikeProperty() { PartTree tree = new PartTree("findByEmailAddressesContaining", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -373,7 +373,7 @@ public void shouldCreateInClauseWhenUsingContainsOnCollectionLikeProperty() { } @Test // DATAMONGO-1075 - public void shouldCreateInClauseWhenUsingNotContainsOnCollectionLikeProperty() { + void shouldCreateInClauseWhenUsingNotContainsOnCollectionLikeProperty() { PartTree tree = new PartTree("findByEmailAddressesNotContaining", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context); @@ -384,7 +384,7 @@ public void shouldCreateInClauseWhenUsingNotContainsOnCollectionLikeProperty() { } @Test // DATAMONGO-1075, DATAMONGO-1425 - public void shouldCreateRegexWhenUsingNotContainsOnStringProperty() { + void shouldCreateRegexWhenUsingNotContainsOnStringProperty() { PartTree tree = new PartTree("findByUsernameNotContaining", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "thew"), context); @@ -395,7 +395,7 @@ public void shouldCreateRegexWhenUsingNotContainsOnStringProperty() { } @Test // DATAMONGO-1139 - public void createsNonSphericalNearForDistanceWithDefaultMetric() { + void createsNonSphericalNearForDistanceWithDefaultMetric() { Point point = new Point(1.0, 1.0); Distance distance = new Distance(1.0); @@ -408,7 +408,7 @@ public void createsNonSphericalNearForDistanceWithDefaultMetric() { } @Test // DATAMONGO-1136 - public void shouldCreateWithinQueryCorrectly() { + void shouldCreateWithinQueryCorrectly() { Point first = new Point(1, 1); Point second = new Point(2, 2); @@ -423,7 +423,7 @@ public void shouldCreateWithinQueryCorrectly() { } @Test // DATAMONGO-1110 - public void shouldCreateNearSphereQueryForSphericalProperty() { + void shouldCreateNearSphereQueryForSphericalProperty() { Point point = new Point(10, 20); @@ -435,7 +435,7 @@ public void shouldCreateNearSphereQueryForSphericalProperty() { } @Test // DATAMONGO-1110 - public void shouldCreateNearSphereQueryForSphericalPropertyHavingDistanceWithDefaultMetric() { + void shouldCreateNearSphereQueryForSphericalPropertyHavingDistanceWithDefaultMetric() { Point point = new Point(1.0, 1.0); Distance distance = new Distance(1.0); @@ -448,7 +448,7 @@ public void shouldCreateNearSphereQueryForSphericalPropertyHavingDistanceWithDef } @Test // DATAMONGO-1110 - public void shouldCreateNearQueryForMinMaxDistance() { + void shouldCreateNearQueryForMinMaxDistance() { Point point = new Point(10, 20); Range range = Distance.between(new Distance(10), new Distance(20)); @@ -461,7 +461,7 @@ public void shouldCreateNearQueryForMinMaxDistance() { } @Test // DATAMONGO-1229 - public void appliesIgnoreCaseToLeafProperty() { + void appliesIgnoreCaseToLeafProperty() { PartTree tree = new PartTree("findByAddressStreetIgnoreCase", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "Street"); @@ -470,7 +470,7 @@ public void appliesIgnoreCaseToLeafProperty() { } @Test // DATAMONGO-1232 - public void ignoreCaseShouldEscapeSource() { + void ignoreCaseShouldEscapeSource() { PartTree tree = new PartTree("findByUsernameIgnoreCase", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "con.flux+"); @@ -481,7 +481,7 @@ public void ignoreCaseShouldEscapeSource() { } @Test // DATAMONGO-1232 - public void ignoreCaseShouldEscapeSourceWhenUsedForStartingWith() { + void ignoreCaseShouldEscapeSourceWhenUsedForStartingWith() { PartTree tree = new PartTree("findByUsernameStartingWithIgnoreCase", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "dawns.light+"); @@ -492,7 +492,7 @@ public void ignoreCaseShouldEscapeSourceWhenUsedForStartingWith() { } @Test // DATAMONGO-1232 - public void ignoreCaseShouldEscapeSourceWhenUsedForEndingWith() { + void ignoreCaseShouldEscapeSourceWhenUsedForEndingWith() { PartTree tree = new PartTree("findByUsernameEndingWithIgnoreCase", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "new.ton+"); @@ -503,7 +503,7 @@ public void ignoreCaseShouldEscapeSourceWhenUsedForEndingWith() { } @Test // DATAMONGO-1232 - public void likeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() { + void likeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() { PartTree tree = new PartTree("findByUsernameLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "*fire.fight+*"); @@ -514,7 +514,7 @@ public void likeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() { } @Test // DATAMONGO-1232 - public void likeShouldEscapeSourceWhenUsedWithLeadingWildcard() { + void likeShouldEscapeSourceWhenUsedWithLeadingWildcard() { PartTree tree = new PartTree("findByUsernameLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "*steel.heart+"); @@ -525,7 +525,7 @@ public void likeShouldEscapeSourceWhenUsedWithLeadingWildcard() { } @Test // DATAMONGO-1232 - public void likeShouldEscapeSourceWhenUsedWithTrailingWildcard() { + void likeShouldEscapeSourceWhenUsedWithTrailingWildcard() { PartTree tree = new PartTree("findByUsernameLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "cala.mity+*"); @@ -535,7 +535,7 @@ public void likeShouldEscapeSourceWhenUsedWithTrailingWildcard() { } @Test // DATAMONGO-1232 - public void likeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() { + void likeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() { PartTree tree = new PartTree("findByUsernameLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "*"); @@ -545,7 +545,7 @@ public void likeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() { } @Test // DATAMONGO-1342 - public void bindsNullValueToContainsClause() { + void bindsNullValueToContainsClause() { PartTree partTree = new PartTree("emailAddressesContains", User.class); @@ -556,7 +556,7 @@ public void bindsNullValueToContainsClause() { } @Test // DATAMONGO-1424 - public void notLikeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() { + void notLikeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() { PartTree tree = new PartTree("findByUsernameNotLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "*fire.fight+*"); @@ -568,7 +568,7 @@ public void notLikeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() { } @Test // DATAMONGO-1424 - public void notLikeShouldEscapeSourceWhenUsedWithLeadingWildcard() { + void notLikeShouldEscapeSourceWhenUsedWithLeadingWildcard() { PartTree tree = new PartTree("findByUsernameNotLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "*steel.heart+"); @@ -580,7 +580,7 @@ public void notLikeShouldEscapeSourceWhenUsedWithLeadingWildcard() { } @Test // DATAMONGO-1424 - public void notLikeShouldEscapeSourceWhenUsedWithTrailingWildcard() { + void notLikeShouldEscapeSourceWhenUsedWithTrailingWildcard() { PartTree tree = new PartTree("findByUsernameNotLike", User.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "cala.mity+*"), context); @@ -591,7 +591,7 @@ public void notLikeShouldEscapeSourceWhenUsedWithTrailingWildcard() { } @Test // DATAMONGO-1424 - public void notLikeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() { + void notLikeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() { PartTree tree = new PartTree("findByUsernameNotLike", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, "*"); @@ -602,7 +602,7 @@ public void notLikeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() { } @Test // DATAMONGO-1588 - public void queryShouldAcceptSubclassOfDeclaredArgument() { + void queryShouldAcceptSubclassOfDeclaredArgument() { PartTree tree = new PartTree("findByLocationNear", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, new GeoJsonPoint(-74.044502D, 40.689247D)); @@ -612,7 +612,7 @@ public void queryShouldAcceptSubclassOfDeclaredArgument() { } @Test // DATAMONGO-1588 - public void queryShouldThrowExceptionWhenArgumentDoesNotMatchDeclaration() { + void queryShouldThrowExceptionWhenArgumentDoesNotMatchDeclaration() { PartTree tree = new PartTree("findByLocationNear", User.class); ConvertingParameterAccessor accessor = getAccessor(converter, @@ -623,7 +623,7 @@ public void queryShouldThrowExceptionWhenArgumentDoesNotMatchDeclaration() { } @Test // DATAMONGO-2003 - public void createsRegexQueryForPatternCorrectly() { + void createsRegexQueryForPatternCorrectly() { PartTree tree = new PartTree("findByFirstNameRegex", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, Pattern.compile(".*")), context); @@ -632,7 +632,7 @@ public void createsRegexQueryForPatternCorrectly() { } @Test // DATAMONGO-2003 - public void createsRegexQueryForPatternWithOptionsCorrectly() { + void createsRegexQueryForPatternWithOptionsCorrectly() { Pattern pattern = Pattern.compile(".*", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); @@ -642,7 +642,7 @@ public void createsRegexQueryForPatternWithOptionsCorrectly() { } @Test // DATAMONGO-2071 - public void betweenShouldAllowSingleRageParameter() { + void betweenShouldAllowSingleRageParameter() { PartTree tree = new PartTree("findByAgeBetween", Person.class); MongoQueryCreator creator = new MongoQueryCreator(tree, @@ -652,7 +652,7 @@ public void betweenShouldAllowSingleRageParameter() { } @Test // DATAMONGO-2394 - public void nearShouldUseMetricDistanceForGeoJsonTypes() { + void nearShouldUseMetricDistanceForGeoJsonTypes() { GeoJsonPoint point = new GeoJsonPoint(27.987901, 86.9165379); PartTree tree = new PartTree("findByLocationNear", User.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java index fe2f447d78..c6c1b140cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java @@ -38,6 +38,7 @@ import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.TextCriteria; import org.springframework.data.mongodb.repository.MongoRepository; @@ -59,33 +60,32 @@ * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) -public class PartTreeMongoQueryUnitTests { +class PartTreeMongoQueryUnitTests { @Mock MongoOperations mongoOperationsMock; @Mock ExecutableFind findOperationMock; - MongoMappingContext mappingContext; + private MongoMappingContext mappingContext; @BeforeEach - public void setUp() { + void setUp() { mappingContext = new MongoMappingContext(); - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDatabaseFactory.class)); - MongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext); + MongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); doReturn(converter).when(mongoOperationsMock).getConverter(); doReturn(findOperationMock).when(mongoOperationsMock).query(any()); } @Test // DATAMOGO-952 - public void rejectsInvalidFieldSpecification() { + void rejectsInvalidFieldSpecification() { assertThatIllegalStateException().isThrownBy(() -> deriveQueryFromMethod("findByLastname", "foo")) .withMessageContaining("findByLastname"); } @Test // DATAMOGO-952 - public void singleFieldJsonIncludeRestrictionShouldBeConsidered() { + void singleFieldJsonIncludeRestrictionShouldBeConsidered() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findByFirstname", "foo"); @@ -93,7 +93,7 @@ public void singleFieldJsonIncludeRestrictionShouldBeConsidered() { } @Test // DATAMOGO-952 - public void multiFieldJsonIncludeRestrictionShouldBeConsidered() { + void multiFieldJsonIncludeRestrictionShouldBeConsidered() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findByFirstnameAndLastname", "foo", "bar"); @@ -102,7 +102,7 @@ public void multiFieldJsonIncludeRestrictionShouldBeConsidered() { } @Test // DATAMOGO-952 - public void multiFieldJsonExcludeRestrictionShouldBeConsidered() { + void multiFieldJsonExcludeRestrictionShouldBeConsidered() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findPersonByFirstnameAndLastname", "foo", "bar"); @@ -111,7 +111,7 @@ public void multiFieldJsonExcludeRestrictionShouldBeConsidered() { } @Test // DATAMOGO-973 - public void shouldAddFullTextParamCorrectlyToDerivedQuery() { + void shouldAddFullTextParamCorrectlyToDerivedQuery() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findPersonByFirstname", "text", TextCriteria.forDefaultLanguage().matching("search")); @@ -120,19 +120,19 @@ public void shouldAddFullTextParamCorrectlyToDerivedQuery() { } @Test // DATAMONGO-1180 - public void propagatesRootExceptionForInvalidQuery() { + void propagatesRootExceptionForInvalidQuery() { assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> deriveQueryFromMethod("findByAge", 1)) .withCauseInstanceOf(JsonParseException.class); } @Test // DATAMONGO-1345, DATAMONGO-1735 - public void doesNotDeriveFieldSpecForNormalDomainType() { + void doesNotDeriveFieldSpecForNormalDomainType() { assertThat(deriveQueryFromMethod("findPersonBy", new Object[0]).getFieldsObject()).isEqualTo(new Document()); } @Test // DATAMONGO-1345 - public void restrictsQueryToFieldsRequiredForProjection() { + void restrictsQueryToFieldsRequiredForProjection() { Document fieldsObject = deriveQueryFromMethod("findPersonProjectedBy", new Object[0]).getFieldsObject(); @@ -141,7 +141,7 @@ public void restrictsQueryToFieldsRequiredForProjection() { } @Test // DATAMONGO-1345 - public void restrictsQueryToFieldsRequiredForDto() { + void restrictsQueryToFieldsRequiredForDto() { Document fieldsObject = deriveQueryFromMethod("findPersonDtoByAge", new Object[] { 42 }).getFieldsObject(); @@ -150,7 +150,7 @@ public void restrictsQueryToFieldsRequiredForDto() { } @Test // DATAMONGO-1345 - public void usesDynamicProjection() { + void usesDynamicProjection() { Document fields = deriveQueryFromMethod("findDynamicallyProjectedBy", ExtendedProjection.class).getFieldsObject(); @@ -160,7 +160,7 @@ public void usesDynamicProjection() { } @Test // DATAMONGO-1500 - public void shouldLeaveParameterConversionToQueryMapper() { + void shouldLeaveParameterConversionToQueryMapper() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findBySex", Sex.FEMALE); @@ -169,7 +169,7 @@ public void shouldLeaveParameterConversionToQueryMapper() { } @Test // DATAMONGO-1729, DATAMONGO-1735 - public void doesNotCreateFieldsObjectForOpenProjection() { + void doesNotCreateFieldsObjectForOpenProjection() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findAllBy"); @@ -177,12 +177,12 @@ public void doesNotCreateFieldsObjectForOpenProjection() { } @Test // DATAMONGO-1865 - public void limitingReturnsTrueIfTreeIsLimiting() { + void limitingReturnsTrueIfTreeIsLimiting() { assertThat(createQueryForMethod("findFirstBy").isLimiting()).isTrue(); } @Test // DATAMONGO-1865 - public void limitingReturnsFalseIfTreeIsNotLimiting() { + void limitingReturnsFalseIfTreeIsNotLimiting() { assertThat(createQueryForMethod("findPersonBy").isLimiting()).isFalse(); } diff --git a/spring-data-mongodb/src/test/resources/logback.xml b/spring-data-mongodb/src/test/resources/logback.xml index f154590864..a36841c97c 100644 --- a/spring-data-mongodb/src/test/resources/logback.xml +++ b/spring-data-mongodb/src/test/resources/logback.xml @@ -13,7 +13,6 @@ - diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 842dd8341b..eac49f37bc 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -4,7 +4,7 @@ [[new-features.3.3]] == What's New in Spring Data MongoDB 3.3 -* Extended support for <> entities. +* Extended support for <> entities. [[new-features.3.2]] == What's New in Spring Data MongoDB 3.2 diff --git a/src/main/asciidoc/reference/document-references.adoc b/src/main/asciidoc/reference/document-references.adoc new file mode 100644 index 0000000000..92badd2fa1 --- /dev/null +++ b/src/main/asciidoc/reference/document-references.adoc @@ -0,0 +1,440 @@ +[[mapping-usage-references]] +=== Using DBRefs + +The mapping framework does not have to store child objects embedded within the document. +You can also store them separately and use a `DBRef` to refer to that document. +When the object is loaded from MongoDB, those references are eagerly resolved so that you get back a mapped object that looks the same as if it had been stored embedded within your top-level document. + +The following example uses a DBRef to refer to a specific document that exists independently of the object in which it is referenced (both classes are shown in-line for brevity's sake): + +==== +[source,java] +---- +@Document +public class Account { + + @Id + private ObjectId id; + private Float total; +} + +@Document +public class Person { + + @Id + private ObjectId id; + @Indexed + private Integer ssn; + @DBRef + private List accounts; +} +---- +==== + +You need not use `@OneToMany` or similar mechanisms because the List of objects tells the mapping framework that you want a one-to-many relationship. +When the object is stored in MongoDB, there is a list of DBRefs rather than the `Account` objects themselves. +When it comes to loading collections of ``DBRef``s it is advisable to restrict references held in collection types to a specific MongoDB collection. +This allows bulk loading of all references, whereas references pointing to different MongoDB collections need to be resolved one by one. + +IMPORTANT: The mapping framework does not handle cascading saves. +If you change an `Account` object that is referenced by a `Person` object, you must save the `Account` object separately. +Calling `save` on the `Person` object does not automatically save the `Account` objects in the `accounts` property. + +``DBRef``s can also be resolved lazily. +In this case the actual `Object` or `Collection` of references is resolved on first access of the property. +Use the `lazy` attribute of `@DBRef` to specify this. +Required properties that are also defined as lazy loading ``DBRef`` and used as constructor arguments are also decorated with the lazy loading proxy making sure to put as little pressure on the database and network as possible. + +TIP: Lazily loaded ``DBRef``s can be hard to debug. +Make sure tooling does not accidentally trigger proxy resolution by e.g. calling `toString()` or some inline debug rendering invoking property getters. +Please consider to enable _trace_ logging for `org.springframework.data.mongodb.core.convert.DefaultDbRefResolver` to gain insight on `DBRef` resolution. + +[[mapping-usage.document-references]] +=== Using Document References + +Using `@DocumentReference` offers a flexible way of referencing entities in MongoDB. +While the goal is the same as when using <>, the store representation is different. +`DBRef` resolves to a document with a fixed structure as outlined in the https://docs.mongodb.com/manual/reference/database-references/[MongoDB Reference documentation]. + +Document references, do not follow a specific format. +They can be literally anything, a single value, an entire document, basically everything that can be stored in MongoDB. +By default, the mapping layer will use the referenced entities _id_ value for storage and retrieval, like in the sample below. + +==== +[source,java] +---- +@Document +class Account { + + @Id + String id; + Float total; +} + +@Document +class Person { + + @Id + String id; + + @DocumentReference <1> + List accounts; +} +---- + +[source,java] +---- +Account account = … + +tempate.insert(account); <2> + +template.update(Person.class) + .matching(where("id").is(…)) + .apply(new Update().push("accounts").value(account)) <3> + .first(); +---- + +[source,json] +---- +{ + "_id" : …, + "accounts" : [ "6509b9e" … ] <4> +} +---- +<1> Mark the collection of `Account` values to be referenced. +<2> The mapping framework does not handle cascading saves, so make sure to persist the referenced entity individually. +<3> Add the reference to the existing entity. +<4> Referenced `Account` entities are represented as an array of their `_id` values. +==== + +The sample above uses an ``_id``-based fetch query (`{ '_id' : ?#{#target} }`) for data retrieval and resolves linked entities eagerly. +It is possible to alter resolution defaults (listed below) using the attributes of `@DocumentReference` + +.@DocumentReference defaults +[cols="2,3,5",options="header"] +|=== +| Attribute | Description | Default + +| `db` +| The target database name for collection lookup. +| `MongoDatabaseFactory.getMongoDatabase()` + +| `collection` +| The target collection name. +| The annotated property's domain type, respectively the value type in case of `Collection` like or `Map` properties, collection name. + +| `lookup` +| The single document lookup query evaluating placeholders via SpEL expressions using `#target` as the marker for a given source value. `Collection` like or `Map` properties combine individual lookups via an `$or` operator. +| An `_id` field based query (`{ '_id' : ?#{#target} }`) using the loaded source value. + +| `sort` +| Used for sorting result documents on server side. +| None by default. +Result order of `Collection` like properties is restored based on the used lookup query on a best-effort basis. + +| `lazy` +| If set to `true` value resolution is delayed upon first access of the property. +| Resolves properties eagerly by default. +|=== + +`@DocumentReference(lookup)` allows defining filter queries that can be different from the `_id` field and therefore offer a flexible way of defining references between entities as demonstrated in the sample below, where the `Publisher` of a book is referenced by its acronym instead of the internal `id`. + +==== +[source,java] +---- +@Document +class Book { + + @Id + ObjectId id; + String title; + List author; + + @Field("publisher_ac") + @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") <1> + Publisher publisher; +} + +@Document +class Publisher { + + @Id + ObjectId id; + String acronym; <1> + String name; + + @DocumentReference(lazy = true) <2> + List books; + +} +---- + +.`Book` document +[source,json] +---- +{ + "_id" : 9a48e32, + "title" : "The Warded Man", + "author" : ["Peter V. Brett"], + "publisher_ac" : "DR" +} +---- + +.`Publisher` document +[source,json] +---- +{ + "_id" : 1a23e45, + "acronym" : "DR", + "name" : "Del Rey", + … +} +---- +<1> Use the `acronym` field to query for entities in the `Publisher` collection. +<2> Lazy load back references to the `Book` collection. +==== + +The above snippet shows the reading side of things when working with custom referenced objects. +Writing requires a bit of additional setup as the mapping information do not express where `#target` stems from. +The mapping layer requires registration of a `Converter` between the target document and `DocumentPointer`, like the one below: + +==== +[source,java] +---- +@WritingConverter +class PublisherReferenceConverter implements Converter> { + + @Override + public DocumentPointer convert(Publisher source) { + return () -> source.getAcronym(); + } +} +---- +==== + +If no `DocumentPointer` converter is provided the target reference document can be computed based on the given lookup query. +In this case the association target properties are evaluated as shown in the following sample. + +==== +[source,java] +---- +@Document +class Book { + + @Id + ObjectId id; + String title; + List author; + + @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") <1> <2> + Publisher publisher; +} + +@Document +class Publisher { + + @Id + ObjectId id; + String acronym; <1> + String name; + + // ... +} +---- + +[source,json] +---- +{ + "_id" : 9a48e32, + "title" : "The Warded Man", + "author" : ["Peter V. Brett"], + "publisher" : { + "acc" : "DOC" + } +} +---- +<1> Use the `acronym` field to query for entities in the `Publisher` collection. +<2> The field value placeholders of the lookup query (like `acc`) is used to form the reference document. +==== + +With all the above in place it is possible to model all kind of associations between entities. +Have a look at the non-exhaustive list of samples below to get feeling for what is possible. + +.Simple Document Reference using _id_ field +==== +[source,java] +---- +class Entity { + @DocumentReference + ReferencedObject ref; +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : "9a48e32" <1> +} + +// referenced object +{ + "_id" : "9a48e32" <1> +} +---- +<1> MongoDB simple type can be directly used without further configuration. +==== + +.Simple Document Reference using _id_ field with explicit lookup query +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") <1> + ReferencedObject ref; +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : "9a48e32" <1> +} + +// referenced object +{ + "_id" : "9a48e32" +} +---- +<1> _target_ defines the reference value itself. +==== + +.Document Reference extracting the `refKey` field for the lookup query +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ '_id' : '?#{refKey}' }") <1> <2> + private ReferencedObject ref; +} +---- + +[source,java] +---- +@WritingConverter +class ToDocumentPointerConverter implements Converter> { + public DocumentPointer convert(ReferencedObject source) { + return () -> new Document("refKey", source.id); <1> + } +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : { + "refKey" : "9a48e32" <1> + } +} + +// referenced object +{ + "_id" : "9a48e32" +} +---- +<1> The key used for obtaining the reference value must be the one used during write. +<2> `refKey` is short for `target.refKey`. +==== + +.Document Reference with multiple values forming the lookup query +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ 'firstname' : '?#{fn}', 'lastname' : '?#{ln}' }") <1> <2> + ReferencedObject ref; +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : { + "fn" : "Josh", <1> + "ln" : "Long" <1> + } +} + +// referenced object +{ + "_id" : "9a48e32", + "firsntame" : "Josh", <2> + "lastname" : "Long", <2> +} +---- +<1> Read/wirte the keys `fn` & `ln` from/to the linkage document based on the lookup query. +<2> Use non _id_ fields for the lookup of the target documents. +==== + +.Document Reference reading from a target collection +==== +[source,java] +---- +class Entity { + @DocumentReference(lookup = "{ '_id' : '?#{id}' }", collection = "?#{collection}") <2> + private ReferencedObject ref; +} +---- + +[source,java] +---- +@WritingConverter +class ToDocumentPointerConverter implements Converter> { + public DocumentPointer convert(ReferencedObject source) { + return () -> new Document("id", source.id) <1> + .append("collection", … ); <2> + } +} +---- + +[source,json] +---- +// entity +{ + "_id" : "8cfb002", + "ref" : { + "id" : "9a48e32", <1> + "collection" : "…" <2> + } +} +---- +<1> Read/wirte the keys `_id` from/to the reference document to use them in the lookup query. +<2> The collection name can be read from the reference document using its key. +==== + +[WARNING] +==== +We know it is tempting to use all kinds of MongoDB query operators in the lookup query and this is fine. +But there a few aspects to consider: + +* Make sure to have indexes in place that support your lookup. +* Mind that resolution requires a server rountrip inducing latency, consider a lazy strategy. +* A collection of document references is bulk loaded using the `$or` operator. + +The original element order is restored in memory on a best-effort basis. +Restoring the order is only possible when using equality expressions and cannot be done when using MongoDB query operators. +In this case results will be ordered as they are received from the store or via the provided `@DocumentReference(sort)` attribute. + +A few more general remarks: + +* Do you use cyclic references? +Ask your self if you need them. +* Lazy document references are hard to debug. +Make sure tooling does not accidentally trigger proxy resolution by e.g. calling `toString()`. +* There is no support for reading document references using reactive infrastructure. +==== diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 9f9a461ee6..f08d03d3f0 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -2,7 +2,10 @@ [[mapping-chapter]] = Mapping -Rich mapping support is provided by the `MappingMongoConverter`. `MappingMongoConverter` has a rich metadata model that provides a full feature set to map domain objects to MongoDB documents. The mapping metadata model is populated by using annotations on your domain objects. However, the infrastructure is not limited to using annotations as the only source of metadata information. The `MappingMongoConverter` also lets you map objects to documents without providing any additional metadata, by following a set of conventions. +Rich mapping support is provided by the `MappingMongoConverter`. `MappingMongoConverter` has a rich metadata model that provides a full feature set to map domain objects to MongoDB documents. +The mapping metadata model is populated by using annotations on your domain objects. +However, the infrastructure is not limited to using annotations as the only source of metadata information. +The `MappingMongoConverter` also lets you map objects to documents without providing any additional metadata, by following a set of conventions. This section describes the features of the `MappingMongoConverter`, including fundamentals, how to use conventions for mapping objects to documents and how to override those conventions with annotation-based mapping metadata. @@ -357,7 +360,10 @@ The `base-package` property tells it where to scan for classes annotated with th [[mapping-usage]] == Metadata-based Mapping -To take full advantage of the object mapping functionality inside the Spring Data MongoDB support, you should annotate your mapped objects with the `@Document` annotation. Although it is not necessary for the mapping framework to have this annotation (your POJOs are mapped correctly, even without any annotations), it lets the classpath scanner find and pre-process your domain objects to extract the necessary metadata. If you do not use this annotation, your application takes a slight performance hit the first time you store a domain object, because the mapping framework needs to build up its internal metadata model so that it knows about the properties of your domain object and how to persist them. The following example shows a domain object: +To take full advantage of the object mapping functionality inside the Spring Data MongoDB support, you should annotate your mapped objects with the `@Document` annotation. +Although it is not necessary for the mapping framework to have this annotation (your POJOs are mapped correctly, even without any annotations), it lets the classpath scanner find and pre-process your domain objects to extract the necessary metadata. +If you do not use this annotation, your application takes a slight performance hit the first time you store a domain object, because the mapping framework needs to build up its internal metadata model so that it knows about the properties of your domain object and how to persist them. +The following example shows a domain object: .Example domain object ==== @@ -759,7 +765,12 @@ mongoOperations.indexOpsFor(Jedi.class) NOTE: The text index feature is disabled by default for MongoDB v.2.4. -Creating a text index allows accumulating several fields into a searchable full-text index. It is only possible to have one text index per collection, so all fields marked with `@TextIndexed` are combined into this index. Properties can be weighted to influence the document score for ranking results. The default language for the text index is English. To change the default language, set the `language` attribute to whichever language you want (for example,`@Document(language="spanish")`). Using a property called `language` or `@Language` lets you define a language override on a per document base. The following example shows how to created a text index and set the language to Spanish: +Creating a text index allows accumulating several fields into a searchable full-text index. +It is only possible to have one text index per collection, so all fields marked with `@TextIndexed` are combined into this index. +Properties can be weighted to influence the document score for ranking results. +The default language for the text index is English.To change the default language, set the `language` attribute to whichever language you want (for example,`@Document(language="spanish")`). +Using a property called `language` or `@Language` lets you define a language override on a per-document base. +The following example shows how to created a text index and set the language to Spanish: .Example Text Index Usage ==== @@ -783,417 +794,7 @@ class Nested { ---- ==== -[[mapping-usage-references]] -=== Using DBRefs - -The mapping framework does not have to store child objects embedded within the document. -You can also store them separately and use a DBRef to refer to that document. -When the object is loaded from MongoDB, those references are eagerly resolved so that you get back a mapped object that looks the same as if it had been stored embedded within your top-level document. - -The following example uses a DBRef to refer to a specific document that exists independently of the object in which it is referenced (both classes are shown in-line for brevity's sake): - -==== -[source,java] ----- -@Document -public class Account { - - @Id - private ObjectId id; - private Float total; -} - -@Document -public class Person { - - @Id - private ObjectId id; - @Indexed - private Integer ssn; - @DBRef - private List accounts; -} ----- -==== - -You need not use `@OneToMany` or similar mechanisms because the List of objects tells the mapping framework that you want a one-to-many relationship. When the object is stored in MongoDB, there is a list of DBRefs rather than the `Account` objects themselves. -When it comes to loading collections of ``DBRef``s it is advisable to restrict references held in collection types to a specific MongoDB collection. This allows bulk loading of all references, whereas references pointing to different MongoDB collections need to be resolved one by one. - -IMPORTANT: The mapping framework does not handle cascading saves. If you change an `Account` object that is referenced by a `Person` object, you must save the `Account` object separately. Calling `save` on the `Person` object does not automatically save the `Account` objects in the `accounts` property. - -``DBRef``s can also be resolved lazily. In this case the actual `Object` or `Collection` of references is resolved on first access of the property. Use the `lazy` attribute of `@DBRef` to specify this. -Required properties that are also defined as lazy loading ``DBRef`` and used as constructor arguments are also decorated with the lazy loading proxy making sure to put as little pressure on the database and network as possible. - -TIP: Lazily loaded ``DBRef``s can be hard to debug. Make sure tooling does not accidentally trigger proxy resolution by eg. calling `toString()` or some inline debug rendering invoking property getters. -Please consider to enable _trace_ logging for `org.springframework.data.mongodb.core.convert.DefaultDbRefResolver` to gain insight on `DBRef` resolution. - -[[mapping-usage.linking]] -=== Using Document References - -Using `@DocumentReference` offers an alternative way of linking entities in MongoDB. -While the goal is the same as when using <>, the store representation is different. -`DBRef` resolves to a document with a fixed structure as outlined in the https://docs.mongodb.com/manual/reference/database-references/[MongoDB Reference documentation]. + -Document references, do not follow a specific format. -They can be literally anything, a single value, an entire document, basically everything that can be stored in MongoDB. -By default, the mapping layer will use the referenced entities _id_ value for storage and retrieval, like in the sample below. - -==== -[source,java] ----- -@Document -public class Account { - - @Id - private String id; - private Float total; -} - -@Document -public class Person { - - @Id - private String id; - - @DocumentReference <1> - private List accounts; -} ----- -[source,java] ----- -Account account = ... - -tempate.insert(account); <2> - -template.update(Person.class) - .matching(where("id").is(...)) - .apply(new Update().push("accounts").value(account)) <3> - .first(); ----- -[source,json] ----- -{ - "_id" : ..., - "accounts" : [ "6509b9e", ... ] <4> -} ----- -<1> Mark the collection of `Account` values to be linked. -<2> The mapping framework does not handle cascading saves, so make sure to persist the referenced entity individually. -<3> Add the reference to the existing entity. -<4> Linked `Account` entities are represented as an array of their `_id` values. -==== - -The sample above uses an `_id` based fetch query (`{ '_id' : ?#{#target} }`) for data retrieval and resolves linked entities eagerly. -It is possible to alter resolution defaults (listed below) via the attributes of `@DocumentReference` - -.@DocumentReference defaults -[cols="2,3,5", options="header"] -|=== -| Attribute | Description | Default - -| `db` -| The target database name for collection lookup. -| The configured database provided by `MongoDatabaseFactory.getMongoDatabase()`. - -| `collection` -| The target collection name. -| The annotated properties domain type, respectively the value type in case of `Collection` like or `Map` properties, collection name. - -| `lookup` -| The single document lookup query evaluating placeholders via SpEL expressions using `#target` as the marker for a given source value. `Collection` like or `Map` properties combine individual lookups via an `$or` operator. -| An `_id` field based query (`{ '_id' : ?#{#target} }`) using the loaded source value. - -| `sort` -| Used for sorting result documents on server side. -| None by default. Result order of `Collection` like properties is restored based on the used lookup query. - -| `lazy` -| If set to `true` value resolution is delayed upon first access of the property. -| Resolves properties eagerly by default. -|=== - -`@DocumentReference(lookup=...)` allows to define custom queries that are independent from the `_id` field and therefore offer a flexible way of defining links between entities as demonstrated in the sample below, where the `Publisher` of a book is referenced by its acronym instead of the internal `id`. - -==== -[source,java] ----- -@Document -public class Book { - - @Id - private ObjectId id; - private String title; - private List author; - - @Field("publisher_ac") - @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") <1> - private Publisher publisher; -} - -@Document -public class Publisher { - - @Id - private ObjectId id; - private String acronym; <1> - private String name; - - @DocumentReference(lazy = true) <2> - private List books; - -} ----- -[source,json] ----- -{ - "_id" : 9a48e32, - "title" : "The Warded Man", - "author" : ["Peter V. Brett"], - "publisher_ac" : "DR" -} ----- -<1> Use the `acronym` field to query for entities in the `Publisher` collection. -<2> Lazy load back references to the `Book` collection. -==== - -The above snipped shows the reading side of things when working with custom linked objects. -To make the writing part aware of the modified document pointer a custom converter, capable of the transformation into a `DocumentPointer`, like the one below, needs to be registered. - -==== -[source,java] ----- -@WritingConverter -class PublisherReferenceConverter implements Converter> { - - @Override - public DocumentPointer convert(Publisher source) { - return () -> source.getAcronym(); - } -} ----- -==== - -If no `DocumentPointer` converter is provided the target linkage document can be computed based on the given lookup query. -In this case the association target properties are evaluated as shown in the following sample. - -==== -[source,java] ----- -@Document -public class Book { - - @Id - private ObjectId id; - private String title; - private List author; - - @DocumentReference(lookup = "{ 'acronym' : ?#{acc} }") <1> <2> - private Publisher publisher; -} - -@Document -public class Publisher { - - @Id - private ObjectId id; - private String acronym; <1> - private String name; - - // ... -} ----- -[source,json] ----- -{ - "_id" : 9a48e32, - "title" : "The Warded Man", - "author" : ["Peter V. Brett"], - "publisher" : { - "acc" : "DOC" - } -} ----- -<1> Use the `acronym` field to query for entities in the `Publisher` collection. -<2> The field value placeholders of the lookup query (like `acc`) is used to form the linkage document. -==== - -With all the above in place it is possible to model all kind of associations between entities. -Have a look at the non exhaustive list of samples below to get feeling for what is possible. - -.Simple Document Reference using _id_ field -==== -[source,java] ----- -class Entity { - @DocumentReference - private ReferencedObject ref; -} ----- - -[source,json] ----- -// entity -{ - "_id" : "8cfb002", - "ref" : "9a48e32" <1> -} - -// referenced object -{ - "_id" : "9a48e32" <1> -} ----- -<1> MongoDB simple type can be directly used without further configuration. -==== - -.Simple Document Reference using _id_ field with explicit lookup query -==== -[source,java] ----- -class Entity { - @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") <1> - private ReferencedObject ref; -} ----- - -[source,json] ----- -// entity -{ - "_id" : "8cfb002", - "ref" : "9a48e32" <1> -} - -// referenced object -{ - "_id" : "9a48e32" -} ----- -<1> _target_ defines the linkage value itself. -==== - -.Document Reference extracting field of linkage document for lookup query -==== -[source,java] ----- -class Entity { - @DocumentReference(lookup = "{ '_id' : '?#{refKey}' }") <1> <2> - private ReferencedObject ref; -} ----- - -[source,java] ----- -@WritingConverter -class ToDocumentPointerConverter implements Converter> { - public DocumentPointer convert(ReferencedObject source) { - return () -> new Document("refKey", source.id); <1> - } -} ----- - -[source,json] ----- -// entity -{ - "_id" : "8cfb002", - "ref" : { - "refKey" : "9a48e32" <1> - } -} - -// referenced object -{ - "_id" : "9a48e32" -} ----- -<1> The key used for obtaining the linkage value must be the one used during write. -<2> `refKey` is short for `target.refKey`. -==== - -.Document Reference with multiple values forming the lookup query -==== -[source,java] ----- -class Entity { - @DocumentReference(lookup = "{ 'firstname' : '?#{fn}', 'lastname' : '?#{ln}' }") <1> <2> - private ReferencedObject ref; -} ----- - -[source,json] ----- -// entity -{ - "_id" : "8cfb002", - "ref" : { - "fn" : "Josh", <1> - "ln" : "Long" <1> - } -} - -// referenced object -{ - "_id" : "9a48e32", - "firsntame" : "Josh", <2> - "lastname" : "Long", <2> -} ----- -<1> Read/wirte the keys `fn` & `ln` from/to the linkage document based on the lookup query. -<2> Use non _id_ fields for the lookup of the target documents. -==== - -.Document Reference reading target collection from linkage document -==== -[source,java] ----- -class Entity { - @DocumentReference(lookup = "{ '_id' : '?#{id}' }", collection = "?#{collection}") <2> - private ReferencedObject ref; -} ----- - -[source,java] ----- -@WritingConverter -class ToDocumentPointerConverter implements Converter> { - public DocumentPointer convert(ReferencedObject source) { - return () -> new Document("id", source.id) <1> - .append("collection", ... ); <2> - } -} ----- - -[source,json] ----- -// entity -{ - "_id" : "8cfb002", - "ref" : { - "id" : "9a48e32", <1> - "collection" : "..." <2> - } -} ----- -<1> Read/wirte the keys `_id` from/to the linkage document to use them in the lookup query. -<2> The collection name can be read from the linkage document via its key. -==== - -[WARNING] -==== -We know it is tempting to use all kinds of MongoDB query operators in the lookup query and this is fine. But: - -* Make sure to have indexes in place that support your lookup. -* Mind that resolution takes time and consider a lazy strategy. -* A collection of document references is bulk loaded using an `$or` operator. + -The original element order is restored in memory which cannot be done when using MongoDB query operators. -In this case Results will be ordered as they are received from the store or via the provided `@DocumentReference(sort = ...)` attribute. - -And a few more general remarks: - -* Cyclic references? Ask your self if you need them. -* Lazy document references are hard to debug. Make sure tooling does not accidentally trigger proxy resolution by eg. calling `toString()`. -* There is no support for reading document references via the reactive bits Spring Data MongoDB offers. -==== +include::document-references.adoc[] [[mapping-usage-events]] === Mapping Framework Events From dae0ac3b4dc1a3fedffd39571352b0323464d03d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 21 May 2021 10:56:58 +0200 Subject: [PATCH 0430/1381] Remove duplicate LazyLoadingInterceptor code by reusing LazyLoadingProxyFactory. Original pull request: #3647. Closes #3602. --- .../core/convert/DefaultDbRefResolver.java | 309 +----------------- .../convert/DefaultReferenceResolver.java | 23 +- .../core/convert/LazyLoadingProxy.java | 4 +- .../core/convert/LazyLoadingProxyFactory.java | 138 +++++--- .../core/convert/ReferenceResolver.java | 14 +- .../DbRefMappingMongoConverterUnitTests.java | 78 ++--- .../DefaultDbRefResolverUnitTests.java | 2 + .../LazyLoadingInterceptorUnitTests.java | 8 +- .../core/convert/LazyLoadingTestUtils.java | 8 +- 9 files changed, 173 insertions(+), 411 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index f64c7f0f06..70fc880cc1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -15,13 +15,6 @@ */ package org.springframework.data.mongodb.core.convert; -import static org.springframework.util.ReflectionUtils.*; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -29,30 +22,18 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.cglib.proxy.Callback; -import org.springframework.cglib.proxy.Enhancer; -import org.springframework.cglib.proxy.Factory; -import org.springframework.cglib.proxy.MethodProxy; -import org.springframework.dao.DataAccessException; + import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.ClientSessionException; -import org.springframework.data.mongodb.LazyLoadingException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoDatabaseUtils; import org.springframework.data.mongodb.core.convert.ReferenceLoader.DocumentReferenceQuery; import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; -import org.springframework.objenesis.ObjenesisStd; import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import com.mongodb.DBRef; @@ -74,8 +55,6 @@ public class DefaultDbRefResolver extends DefaultReferenceResolver implements Db private static final Logger LOGGER = LoggerFactory.getLogger(DefaultDbRefResolver.class); private final MongoDatabaseFactory mongoDbFactory; - private final PersistenceExceptionTranslator exceptionTranslator; - private final ObjenesisStd objenesis; /** * Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDatabaseFactory}. @@ -84,13 +63,11 @@ public class DefaultDbRefResolver extends DefaultReferenceResolver implements Db */ public DefaultDbRefResolver(MongoDatabaseFactory mongoDbFactory) { - super(new MongoDatabaseFactoryReferenceLoader(mongoDbFactory)); + super(new MongoDatabaseFactoryReferenceLoader(mongoDbFactory), mongoDbFactory.getExceptionTranslator()); Assert.notNull(mongoDbFactory, "MongoDbFactory translator must not be null!"); this.mongoDbFactory = mongoDbFactory; - this.exceptionTranslator = mongoDbFactory.getExceptionTranslator(); - this.objenesis = new ObjenesisStd(true); } /* @@ -180,44 +157,9 @@ public List bulkFetch(List refs) { private Object createLazyLoadingProxy(MongoPersistentProperty property, @Nullable DBRef dbref, DbRefResolverCallback callback, DbRefProxyHandler handler) { - Class propertyType = property.getType(); - LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, dbref, exceptionTranslator, callback); - - if (!propertyType.isInterface()) { - - Factory factory = (Factory) objenesis.newInstance(getEnhancedTypeFor(propertyType)); - factory.setCallbacks(new Callback[] { interceptor }); - - return handler.populateId(property, dbref, factory); - } - - ProxyFactory proxyFactory = new ProxyFactory(); - - for (Class type : propertyType.getInterfaces()) { - proxyFactory.addInterface(type); - } - - proxyFactory.addInterface(LazyLoadingProxy.class); - proxyFactory.addInterface(propertyType); - proxyFactory.addAdvice(interceptor); + Object lazyLoadingProxy = getProxyFactory().createLazyLoadingProxy(property, callback, dbref); - return handler.populateId(property, dbref, proxyFactory.getProxy(LazyLoadingProxy.class.getClassLoader())); - } - - /** - * Returns the CGLib enhanced type for the given source type. - * - * @param type - * @return - */ - private Class getEnhancedTypeFor(Class type) { - - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(type); - enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); - enhancer.setInterfaces(new Class[] { LazyLoadingProxy.class }); - - return enhancer.createClass(); + return handler.populateId(property, dbref, lazyLoadingProxy); } /** @@ -244,249 +186,6 @@ private static Stream documentWithId(Object identifier, Collection getReferenceLoader().fetchMany(filter, ctx); private final LookupFunction singleValueLookupFunction = (filter, ctx) -> { @@ -43,13 +47,17 @@ public class DefaultReferenceResolver implements ReferenceResolver { /** * Create a new instance of {@link DefaultReferenceResolver}. - * + * * @param referenceLoader must not be {@literal null}. + * @param exceptionTranslator must not be {@literal null}. */ - public DefaultReferenceResolver(ReferenceLoader referenceLoader) { - + public DefaultReferenceResolver(ReferenceLoader referenceLoader, PersistenceExceptionTranslator exceptionTranslator) { + Assert.notNull(referenceLoader, "ReferenceLoader must not be null!"); + Assert.notNull(exceptionTranslator, "ExceptionTranslator must not be null!"); + this.referenceLoader = referenceLoader; + this.proxyFactory = new LazyLoadingProxyFactory(exceptionTranslator); } @Override @@ -92,9 +100,14 @@ protected ReferenceLoader getReferenceLoader() { return referenceLoader; } + LazyLoadingProxyFactory getProxyFactory() { + return proxyFactory; + } + private Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, ReferenceLookupDelegate referenceLookupDelegate, LookupFunction lookupFunction, MongoEntityReader entityReader) { - return new LazyLoadingProxyFactory(referenceLookupDelegate).createLazyLoadingProxy(property, source, lookupFunction, - entityReader); + return proxyFactory.createLazyLoadingProxy(property, it -> { + return referenceLookupDelegate.readReference(it, source, lookupFunction, entityReader); + }, source); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java index 8be7111988..a2a2df8c86 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxy.java @@ -15,18 +15,18 @@ */ package org.springframework.data.mongodb.core.convert; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.LazyLoadingInterceptor; import org.springframework.lang.Nullable; import com.mongodb.DBRef; /** - * Allows direct interaction with the underlying {@link LazyLoadingInterceptor}. + * Allows direct interaction with the underlying {@code LazyLoadingInterceptor}. * * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch * @since 1.5 + * @see LazyLoadingProxyFactory */ public interface LazyLoadingProxy { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java index 8c2156df2e..f77b96c71f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java @@ -15,46 +15,59 @@ */ package org.springframework.data.mongodb.core.convert; -import static org.springframework.data.mongodb.core.convert.ReferenceLookupDelegate.*; import static org.springframework.util.ReflectionUtils.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodProxy; -import org.springframework.data.mongodb.core.convert.ReferenceResolver.MongoEntityReader; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.mongodb.ClientSessionException; +import org.springframework.data.mongodb.LazyLoadingException; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.lang.Nullable; import org.springframework.objenesis.ObjenesisStd; import org.springframework.util.ReflectionUtils; +import com.mongodb.DBRef; + /** + * {@link ProxyFactory} to create a proxy for {@link MongoPersistentProperty#getType()} to resolve a reference lazily. + * * @author Christoph Strobl + * @author Mark Paluch */ class LazyLoadingProxyFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(LazyLoadingProxyFactory.class); + private final ObjenesisStd objenesis; - private final ReferenceLookupDelegate lookupDelegate; - public LazyLoadingProxyFactory(ReferenceLookupDelegate lookupDelegate) { + private final PersistenceExceptionTranslator exceptionTranslator; - this.lookupDelegate = lookupDelegate; + public LazyLoadingProxyFactory(PersistenceExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; this.objenesis = new ObjenesisStd(true); } - public Object createLazyLoadingProxy(MongoPersistentProperty property, Object source, LookupFunction lookupFunction, - MongoEntityReader entityReader) { + public Object createLazyLoadingProxy(MongoPersistentProperty property, DbRefResolverCallback callback, + Object source) { Class propertyType = property.getType(); - LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, source, lookupDelegate, lookupFunction, - entityReader); + LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, callback, source, exceptionTranslator); if (!propertyType.isInterface()) { @@ -96,17 +109,9 @@ private Class getEnhancedTypeFor(Class type) { public static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor, Serializable { - private final ReferenceLookupDelegate referenceLookupDelegate; - private final MongoPersistentProperty property; - private volatile boolean resolved; - private @Nullable Object result; - private final Object source; - private final LookupFunction lookupFunction; - private final MongoEntityReader entityReader; - - private final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD, GET_SOURCE_METHOD; + private static final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD, GET_SOURCE_METHOD; - { + static { try { INITIALIZE_METHOD = LazyLoadingProxy.class.getMethod("getTarget"); TO_DBREF_METHOD = LazyLoadingProxy.class.getMethod("toDBRef"); @@ -117,14 +122,20 @@ public static class LazyLoadingInterceptor } } - public LazyLoadingInterceptor(MongoPersistentProperty property, Object source, ReferenceLookupDelegate reader, - LookupFunction lookupFunction, MongoEntityReader entityReader) { + private final MongoPersistentProperty property; + private final DbRefResolverCallback callback; + private final Object source; + private final PersistenceExceptionTranslator exceptionTranslator; + private volatile boolean resolved; + private @Nullable Object result; + + public LazyLoadingInterceptor(MongoPersistentProperty property, DbRefResolverCallback callback, Object source, + PersistenceExceptionTranslator exceptionTranslator) { this.property = property; + this.callback = callback; this.source = source; - this.referenceLookupDelegate = reader; - this.lookupFunction = lookupFunction; - this.entityReader = entityReader; + this.exceptionTranslator = exceptionTranslator; } @Nullable @@ -142,7 +153,7 @@ public Object intercept(Object o, Method method, Object[] args, MethodProxy prox } if (TO_DBREF_METHOD.equals(method)) { - return null; + return source instanceof DBRef ? source : null; } if (GET_SOURCE_METHOD.equals(method)) { @@ -152,7 +163,7 @@ public Object intercept(Object o, Method method, Object[] args, MethodProxy prox if (isObjectMethod(method) && Object.class.equals(method.getDeclaringClass())) { if (ReflectionUtils.isToStringMethod(method)) { - return proxyToString(proxy); + return proxyToString(source); } if (ReflectionUtils.isEqualsMethod(method)) { @@ -160,7 +171,7 @@ public Object intercept(Object o, Method method, Object[] args, MethodProxy prox } if (ReflectionUtils.isHashCodeMethod(method)) { - return proxyHashCode(proxy); + return proxyHashCode(); } // DATAMONGO-1076 - finalize methods should not trigger proxy initialization @@ -195,7 +206,13 @@ private String proxyToString(@Nullable Object source) { StringBuilder description = new StringBuilder(); if (source != null) { - description.append(source); + if (source instanceof DBRef) { + description.append(((DBRef) source).getCollectionName()); + description.append(":"); + description.append(((DBRef) source).getId()); + } else { + description.append(source); + } } else { description.append(System.identityHashCode(source)); } @@ -217,8 +234,36 @@ private boolean proxyEquals(@Nullable Object proxy, Object that) { return proxyToString(proxy).equals(that.toString()); } - private int proxyHashCode(@Nullable Object proxy) { - return proxyToString(proxy).hashCode(); + private int proxyHashCode() { + return proxyToString(source).hashCode(); + } + + /** + * Callback method for serialization. + * + * @param out + * @throws IOException + */ + private void writeObject(ObjectOutputStream out) throws IOException { + + ensureResolved(); + out.writeObject(this.result); + } + + /** + * Callback method for deserialization. + * + * @param in + * @throws IOException + */ + private void readObject(ObjectInputStream in) throws IOException { + + try { + this.resolved = true; + this.result = in.readObject(); + } catch (ClassNotFoundException e) { + throw new LazyLoadingException("Could not deserialize result", e); + } } @Nullable @@ -226,32 +271,31 @@ private synchronized Object resolve() { if (resolved) { - // if (LOGGER.isTraceEnabled()) { - // LOGGER.trace("Accessing already resolved lazy loading property {}.{}", - // property.getOwner() != null ? property.getOwner().getName() : "unknown", property.getName()); - // } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Accessing already resolved lazy loading property {}.{}", + property.getOwner() != null ? property.getOwner().getName() : "unknown", property.getName()); + } return result; } try { - // if (LOGGER.isTraceEnabled()) { - // LOGGER.trace("Resolving lazy loading property {}.{}", - // property.getOwner() != null ? property.getOwner().getName() : "unknown", property.getName()); - // } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Resolving lazy loading property {}.{}", + property.getOwner() != null ? property.getOwner().getName() : "unknown", property.getName()); + } - return referenceLookupDelegate.readReference(property, source, lookupFunction, entityReader); + return callback.resolve(property); } catch (RuntimeException ex) { - throw ex; - // DataAccessException translatedException = this.exceptionTranslator.translateExceptionIfPossible(ex); - // - // if (translatedException instanceof ClientSessionException) { - // throw new LazyLoadingException("Unable to lazily resolve DBRef! Invalid session state.", ex); - // } + DataAccessException translatedException = exceptionTranslator.translateExceptionIfPossible(ex); + + if (translatedException instanceof ClientSessionException) { + throw new LazyLoadingException("Unable to lazily resolve DBRef! Invalid session state.", ex); + } - // throw new LazyLoadingException("Unable to lazily resolve DBRef!", - // translatedException != null ? translatedException : ex); + throw new LazyLoadingException("Unable to lazily resolve DBRef!", + translatedException != null ? translatedException : ex); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java index 91235b5270..c2cf676604 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceResolver.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.convert; +import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.util.TypeInformation; @@ -27,12 +28,15 @@ * The {@link ReferenceResolver} allows to load and convert linked entities. * * @author Christoph Strobl + * @since 3.3 */ +@FunctionalInterface public interface ReferenceResolver { /** - * Resolve the association defined via the given property from a given source value. May deliver a - * {@link LazyLoadingProxy proxy instance} in case of a lazy loading association. + * Resolve the association defined via the given property from a given source value. May return a + * {@link LazyLoadingProxy proxy instance} in case of a lazy loading association. The resolved value is assignable to + * {@link PersistentProperty#getType()}. * * @param property the association defining property. * @param source the association source value. @@ -79,7 +83,7 @@ public static ReferenceCollection fromDBRef(DBRef dbRef) { /** * Get the target collection name. - * + * * @return never {@literal null}. */ public String getCollection() { @@ -98,7 +102,7 @@ public String getDatabase() { } /** - * Domain type conversion callback interface that allows to read + * Domain type conversion callback interface that allows to read the {@code source} object into a mapped object. */ @FunctionalInterface interface MongoEntityReader { @@ -107,7 +111,7 @@ interface MongoEntityReader { * Read values from the given source into an object defined via the given {@link TypeInformation}. * * @param source never {@literal null}. - * @param typeInformation information abount the desired target type. + * @param typeInformation information about the desired target type. * @return never {@literal null}. */ Object read(Object source, TypeInformation typeInformation); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index 84e7e2c2d8..d5285e7d2e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -70,16 +70,16 @@ * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) -public class DbRefMappingMongoConverterUnitTests { +class DbRefMappingMongoConverterUnitTests { - MappingMongoConverter converter; - MongoMappingContext mappingContext; + private MappingMongoConverter converter; + private MongoMappingContext mappingContext; @Mock MongoDatabaseFactory dbFactory; - DefaultDbRefResolver dbRefResolver; + private DefaultDbRefResolver dbRefResolver; @BeforeEach - public void setUp() { + void setUp() { when(dbFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); @@ -89,7 +89,7 @@ public void setUp() { } @Test // DATAMONGO-347 - public void createsSimpleDBRefCorrectly() { + void createsSimpleDBRefCorrectly() { Person person = new Person(); person.id = "foo"; @@ -100,7 +100,7 @@ public void createsSimpleDBRefCorrectly() { } @Test // DATAMONGO-657 - public void convertDocumentWithMapDBRef() { + void convertDocumentWithMapDBRef() { Document mapValDocument = new Document(); mapValDocument.put("_id", BigInteger.ONE); @@ -145,7 +145,7 @@ public void convertDocumentWithMapDBRef() { } @Test // DATAMONGO-347 - public void createsDBRefWithClientSpecCorrectly() { + void createsDBRefWithClientSpecCorrectly() { PropertyPath path = PropertyPath.from("person", PersonClient.class); MongoPersistentProperty property = mappingContext.getPersistentPropertyPath(path).getLeafProperty(); @@ -159,7 +159,7 @@ public void createsDBRefWithClientSpecCorrectly() { } @Test // DATAMONGO-348 - public void lazyLoadingProxyForLazyDbRefOnInterface() { + void lazyLoadingProxyForLazyDbRefOnInterface() { String id = "42"; String value = "bubu"; @@ -180,7 +180,7 @@ public void lazyLoadingProxyForLazyDbRefOnInterface() { } @Test // DATAMONGO-348 - public void lazyLoadingProxyForLazyDbRefOnConcreteCollection() { + void lazyLoadingProxyForLazyDbRefOnConcreteCollection() { String id = "42"; String value = "bubu"; @@ -201,7 +201,7 @@ public void lazyLoadingProxyForLazyDbRefOnConcreteCollection() { } @Test // DATAMONGO-348 - public void lazyLoadingProxyForLazyDbRefOnConcreteType() { + void lazyLoadingProxyForLazyDbRefOnConcreteType() { String id = "42"; String value = "bubu"; @@ -222,7 +222,7 @@ public void lazyLoadingProxyForLazyDbRefOnConcreteType() { } @Test // DATAMONGO-348 - public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructor() { + void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructor() { String id = "42"; String value = "bubu"; @@ -243,7 +243,7 @@ public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructor } @Test // DATAMONGO-348 - public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructorButWithoutDefaultConstructor() { + void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructorButWithoutDefaultConstructor() { String id = "42"; String value = "bubu"; @@ -266,7 +266,7 @@ public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructor } @Test // DATAMONGO-348 - public void lazyLoadingProxyForSerializableLazyDbRefOnConcreteType() { + void lazyLoadingProxyForSerializableLazyDbRefOnConcreteType() { String id = "42"; String value = "bubu"; @@ -288,7 +288,7 @@ public void lazyLoadingProxyForSerializableLazyDbRefOnConcreteType() { } @Test // DATAMONGO-884 - public void lazyLoadingProxyForToStringObjectMethodOverridingDbref() { + void lazyLoadingProxyForToStringObjectMethodOverridingDbref() { String id = "42"; String value = "bubu"; @@ -309,7 +309,7 @@ public void lazyLoadingProxyForToStringObjectMethodOverridingDbref() { } @Test // DATAMONGO-884 - public void callingToStringObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { + void callingToStringObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { String id = "42"; String value = "bubu"; @@ -337,7 +337,7 @@ public void callingToStringObjectMethodOnLazyLoadingDbrefShouldNotInitializeProx } @Test // DATAMONGO-884 - public void equalsObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { + void equalsObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { String id = "42"; String value = "bubu"; @@ -362,7 +362,7 @@ public void equalsObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { } @Test // DATAMONGO-884 - public void hashcodeObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { + void hashcodeObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { String id = "42"; String value = "bubu"; @@ -385,7 +385,7 @@ public void hashcodeObjectMethodOnLazyLoadingDbrefShouldNotInitializeProxy() { } @Test // DATAMONGO-884 - public void lazyLoadingProxyForEqualsAndHashcodeObjectMethodOverridingDbref() { + void lazyLoadingProxyForEqualsAndHashcodeObjectMethodOverridingDbref() { String id = "42"; String value = "bubu"; @@ -414,7 +414,7 @@ public void lazyLoadingProxyForEqualsAndHashcodeObjectMethodOverridingDbref() { } @Test // DATAMONGO-987 - public void shouldNotGenerateLazyLoadingProxyForNullValues() { + void shouldNotGenerateLazyLoadingProxyForNullValues() { Document document = new Document(); ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); @@ -432,7 +432,7 @@ public void shouldNotGenerateLazyLoadingProxyForNullValues() { } @Test // DATAMONGO-1005 - public void shouldBeAbleToStoreDirectReferencesToSelf() { + void shouldBeAbleToStoreDirectReferencesToSelf() { Document document = new Document(); @@ -448,7 +448,7 @@ public void shouldBeAbleToStoreDirectReferencesToSelf() { } @Test // DATAMONGO-1005 - public void shouldBeAbleToStoreNestedReferencesToSelf() { + void shouldBeAbleToStoreNestedReferencesToSelf() { Document document = new Document(); @@ -467,7 +467,7 @@ public void shouldBeAbleToStoreNestedReferencesToSelf() { } @Test // DATAMONGO-1012 - public void shouldEagerlyResolveIdPropertyWithFieldAccess() { + void shouldEagerlyResolveIdPropertyWithFieldAccess() { MongoPersistentEntity entity = mappingContext.getRequiredPersistentEntity(ClassWithLazyDbRefs.class); MongoPersistentProperty property = entity.getRequiredPersistentProperty("dbRefToConcreteType"); @@ -489,7 +489,7 @@ public void shouldEagerlyResolveIdPropertyWithFieldAccess() { } @Test // DATAMONGO-1012 - public void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() { + void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() { MongoPersistentEntity entity = mappingContext.getRequiredPersistentEntity(ClassWithLazyDbRefs.class); MongoPersistentProperty property = entity.getRequiredPersistentProperty("dbRefToConcreteTypeWithPropertyAccess"); @@ -507,7 +507,7 @@ public void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() { } @Test // DATAMONGO-1076 - public void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoked() throws Exception { + void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoked() throws Exception { MongoPersistentEntity entity = mappingContext .getRequiredPersistentEntity(WithObjectMethodOverrideLazyDbRefs.class); @@ -525,7 +525,7 @@ public void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoke } @Test // DATAMONGO-1194 - public void shouldBulkFetchListOfReferences() { + void shouldBulkFetchListOfReferences() { String id1 = "1"; String id2 = "2"; @@ -553,7 +553,7 @@ public void shouldBulkFetchListOfReferences() { } @Test // DATAMONGO-1666 - public void shouldBulkFetchSetOfReferencesForConstructorCreation() { + void shouldBulkFetchSetOfReferencesForConstructorCreation() { String id1 = "1"; String id2 = "2"; @@ -575,7 +575,7 @@ public void shouldBulkFetchSetOfReferencesForConstructorCreation() { } @Test // DATAMONGO-1194 - public void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointToDifferentCollections() { + void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointToDifferentCollections() { String id1 = "1"; String id2 = "2"; @@ -603,7 +603,7 @@ public void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointT } @Test // DATAMONGO-1194 - public void shouldBulkFetchMapOfReferences() { + void shouldBulkFetchMapOfReferences() { MapDBRefVal val1 = new MapDBRefVal(); val1.id = BigInteger.ONE; @@ -635,7 +635,7 @@ public void shouldBulkFetchMapOfReferences() { } @Test // DATAMONGO-1194 - public void shouldBulkFetchLazyMapOfReferences() { + void shouldBulkFetchLazyMapOfReferences() { MapDBRefVal val1 = new MapDBRefVal(); val1.id = BigInteger.ONE; @@ -722,15 +722,15 @@ static class LazyDbRefTarget implements Serializable { @Id String id; String value; - public LazyDbRefTarget() { + LazyDbRefTarget() { this(null); } - public LazyDbRefTarget(String id) { + LazyDbRefTarget(String id) { this(id, null); } - public LazyDbRefTarget(String id, String value) { + LazyDbRefTarget(String id, String value) { this.id = id; this.value = value; } @@ -750,7 +750,7 @@ static class LazyDbRefTargetPropertyAccess implements Serializable { @Id @AccessType(Type.PROPERTY) String id; - public LazyDbRefTargetPropertyAccess(String id) { + LazyDbRefTargetPropertyAccess(String id) { this.id = id; } @@ -767,7 +767,7 @@ static class LazyDbRefTargetWithPeristenceConstructor extends LazyDbRefTarget { public LazyDbRefTargetWithPeristenceConstructor() {} @PersistenceConstructor - public LazyDbRefTargetWithPeristenceConstructor(String id, String value) { + LazyDbRefTargetWithPeristenceConstructor(String id, String value) { super(id, value); this.persistenceConstructorCalled = true; } @@ -783,7 +783,7 @@ static class LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor e boolean persistenceConstructorCalled; @PersistenceConstructor - public LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor(String id, String value) { + LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor(String id, String value) { super(id, value); this.persistenceConstructorCalled = true; } @@ -797,7 +797,7 @@ static class SerializableLazyDbRefTarget extends LazyDbRefTarget implements Seri public SerializableLazyDbRefTarget() {} - public SerializableLazyDbRefTarget(String id, String value) { + SerializableLazyDbRefTarget(String id, String value) { super(id, value); } @@ -810,7 +810,7 @@ static class ToStringObjectMethodOverrideLazyDbRefTarget extends LazyDbRefTarget public ToStringObjectMethodOverrideLazyDbRefTarget() {} - public ToStringObjectMethodOverrideLazyDbRefTarget(String id, String value) { + ToStringObjectMethodOverrideLazyDbRefTarget(String id, String value) { super(id, value); } @@ -830,7 +830,7 @@ static class EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget extends LazyDb public EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget() {} - public EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget(String id, String value) { + EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget(String id, String value) { super(id, value); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index d7a2870477..a65214610e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -37,6 +37,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.DocumentTestUtils; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; import com.mongodb.DBRef; import com.mongodb.client.FindIterable; @@ -63,6 +64,7 @@ class DefaultDbRefResolverUnitTests { void setUp() { when(factoryMock.getMongoDatabase()).thenReturn(dbMock); + when(factoryMock.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); when(dbMock.getCollection(anyString(), any(Class.class))).thenReturn(collectionMock); when(collectionMock.find(any(Document.class))).thenReturn(cursorMock); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java index 5b758136e4..d357ca0f85 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingInterceptorUnitTests.java @@ -26,7 +26,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.LazyLoadingException; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.LazyLoadingInterceptor; +import org.springframework.data.mongodb.core.convert.LazyLoadingProxyFactory.LazyLoadingInterceptor; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import com.mongodb.DBRef; @@ -37,20 +37,20 @@ * @author Christoph Strobl */ @ExtendWith(MockitoExtension.class) -public class LazyLoadingInterceptorUnitTests { +class LazyLoadingInterceptorUnitTests { @Mock MongoPersistentProperty propertyMock; @Mock DBRef dbrefMock; @Mock DbRefResolverCallback callbackMock; @Test // DATAMONGO-1437 - public void shouldPreserveCauseForNonTranslatableExceptions() throws Throwable { + void shouldPreserveCauseForNonTranslatableExceptions() throws Throwable { NullPointerException npe = new NullPointerException("Some Exception we did not think about."); when(callbackMock.resolve(propertyMock)).thenThrow(npe); assertThatExceptionOfType(LazyLoadingException.class).isThrownBy(() -> { - new LazyLoadingInterceptor(propertyMock, dbrefMock, new NullExceptionTranslator(), callbackMock).intercept(null, + new LazyLoadingInterceptor(propertyMock, callbackMock, dbrefMock, new NullExceptionTranslator()).intercept(null, LazyLoadingProxy.class.getMethod("getTarget"), null, null); }).withCause(npe); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java index 91afb8c6ec..15e953930c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java @@ -16,12 +16,12 @@ package org.springframework.data.mongodb.core.convert; import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.convert.LazyLoadingProxyFactory.*; import java.util.function.Consumer; import org.springframework.aop.framework.Advised; import org.springframework.cglib.proxy.Factory; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.LazyLoadingInterceptor; import org.springframework.data.mongodb.core.mapping.Unwrapped; import org.springframework.test.util.ReflectionTestUtils; @@ -54,7 +54,7 @@ public static void assertProxyIsResolved(Object target, boolean expected) { public static void assertProxy(Object proxy, Consumer verification) { - LazyLoadingProxyFactory.LazyLoadingInterceptor interceptor = (LazyLoadingProxyFactory.LazyLoadingInterceptor) (proxy instanceof Advised + LazyLoadingInterceptor interceptor = (LazyLoadingInterceptor) (proxy instanceof Advised ? ((Advised) proxy).getAdvisors()[0].getAdvice() : ((Factory) proxy).getCallback(0)); @@ -68,9 +68,9 @@ private static LazyLoadingInterceptor extractInterceptor(Object proxy) { public static class LazyLoadingProxyValueRetriever { - LazyLoadingProxyFactory.LazyLoadingInterceptor interceptor; + LazyLoadingInterceptor interceptor; - public LazyLoadingProxyValueRetriever(LazyLoadingProxyFactory.LazyLoadingInterceptor interceptor) { + public LazyLoadingProxyValueRetriever(LazyLoadingInterceptor interceptor) { this.interceptor = interceptor; } From ece261aadb6e6ec5d94f15df63ca7fac1fce2cee Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 31 May 2021 09:58:30 +0200 Subject: [PATCH 0431/1381] Fix conversion for types having a converter registered. Fixes: #3660 Original pull request: #3662. --- .../core/convert/MappingMongoConverter.java | 14 +- .../MappingMongoConverterUnitTests.java | 196 ++++++++++++++++++ 2 files changed, 206 insertions(+), 4 deletions(-) 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 413ce2ce44..d41decf3ed 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 @@ -171,7 +171,7 @@ protected ConversionContext getConversionContext(ObjectPath path) { Assert.notNull(path, "ObjectPath must not be null"); - return new ConversionContext(path, this::readDocument, this::readCollectionOrArray, this::readMap, this::readDBRef, + return new ConversionContext(conversions, path, this::readDocument, this::readCollectionOrArray, this::readMap, this::readDBRef, this::getPotentiallyConvertedSimpleRead); } @@ -1323,7 +1323,7 @@ protected Map readMap(ConversionContext context, Bson bson, Type } Object value = entry.getValue(); - map.put(key, context.convert(value, valueType)); + map.put(key, value == null ? value : context.convert(value, valueType)); } return map; @@ -1970,6 +1970,7 @@ public org.springframework.data.util.TypeInformation specialize(Cla */ protected static class ConversionContext { + private final org.springframework.data.convert.CustomConversions conversions; private final ObjectPath path; private final ContainerValueConverter documentConverter; private final ContainerValueConverter> collectionConverter; @@ -1977,10 +1978,11 @@ protected static class ConversionContext { private final ContainerValueConverter dbRefConverter; private final ValueConverter elementConverter; - ConversionContext(ObjectPath path, ContainerValueConverter documentConverter, + ConversionContext(org.springframework.data.convert.CustomConversions customConversions, ObjectPath path, ContainerValueConverter documentConverter, ContainerValueConverter> collectionConverter, ContainerValueConverter mapConverter, ContainerValueConverter dbRefConverter, ValueConverter elementConverter) { + this.conversions = customConversions; this.path = path; this.documentConverter = documentConverter; this.collectionConverter = collectionConverter; @@ -2001,6 +2003,10 @@ public S convert(Object source, TypeInformation Assert.notNull(typeHint, "TypeInformation must not be null"); + if (conversions.hasCustomReadTarget(source.getClass(), typeHint.getType())) { + return (S) elementConverter.convert(source, typeHint); + } + if (source instanceof Collection) { Class rawType = typeHint.getType(); @@ -2046,7 +2052,7 @@ public ConversionContext withPath(ObjectPath currentPath) { Assert.notNull(currentPath, "ObjectPath must not be null"); - return new ConversionContext(currentPath, documentConverter, collectionConverter, mapConverter, dbRefConverter, + return new ConversionContext(conversions, currentPath, documentConverter, collectionConverter, mapConverter, dbRefConverter, elementConverter); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index bd3e98788f..441b8e3347 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -81,6 +81,8 @@ import org.springframework.data.mongodb.core.mapping.Unwrapped; import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback; import org.springframework.data.util.ClassTypeInformation; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.BasicDBList; @@ -2428,6 +2430,98 @@ void shouldUseMostConcreteCustomConversionTargetOnRead() { verify(subTypeOfGenericTypeConverter).convert(eq(source)); } + + @Test // GH-3660 + void usesCustomConverterForMapTypesOnWrite() { + + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(it -> { + it.registerConverter(new TypeImplementingMapToDocumentConverter()); + })); + converter.afterPropertiesSet(); + + TypeImplementingMap source = new TypeImplementingMap("one", 2); + org.bson.Document target = new org.bson.Document(); + + converter.write(source, target); + + assertThat(target).containsEntry("1st", "one").containsEntry("2nd", 2); + } + + @Test // GH-3660 + void usesCustomConverterForTypesImplementingMapOnWrite() { + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(it -> { + it.registerConverter(new TypeImplementingMapToDocumentConverter()); + })); + converter.afterPropertiesSet(); + + TypeImplementingMap source = new TypeImplementingMap("one", 2); + org.bson.Document target = new org.bson.Document(); + + converter.write(source, target); + + assertThat(target).containsEntry("1st", "one").containsEntry("2nd", 2); + } + + @Test // GH-3660 + void usesCustomConverterForTypesImplementingMapOnRead() { + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(it -> { + it.registerConverter(new DocumentToTypeImplementingMapConverter()); + })); + converter.afterPropertiesSet(); + + org.bson.Document source = new org.bson.Document("1st", "one") + .append("2nd", 2) + .append("_class", TypeImplementingMap.class.getName()); + + TypeImplementingMap target = converter.read(TypeImplementingMap.class, source); + + assertThat(target).isEqualTo(new TypeImplementingMap("one", 2)); + } + + @Test // GH-3660 + void usesCustomConverterForPropertiesUsingTypesThatImplementMapOnWrite() { + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(it -> { + it.registerConverter(new TypeImplementingMapToDocumentConverter()); + })); + converter.afterPropertiesSet(); + + TypeWrappingTypeImplementingMap source = new TypeWrappingTypeImplementingMap(); + source.typeImplementingMap = new TypeImplementingMap("one", 2); + org.bson.Document target = new org.bson.Document(); + + converter.write(source, target); + + assertThat(target).containsEntry("typeImplementingMap", new org.bson.Document("1st", "one").append("2nd", 2)); + } + + @Test // GH-3660 + void usesCustomConverterForPropertiesUsingTypesImplementingMapOnRead() { + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(it -> { + it.registerConverter(new DocumentToTypeImplementingMapConverter()); + })); + converter.afterPropertiesSet(); + + org.bson.Document source = new org.bson.Document("typeImplementingMap", + new org.bson.Document("1st", "one") + .append("2nd", 2)) + .append("_class", TypeWrappingTypeImplementingMap.class.getName()); + + TypeWrappingTypeImplementingMap target = converter.read(TypeWrappingTypeImplementingMap.class, source); + + assertThat(target.typeImplementingMap).isEqualTo(new TypeImplementingMap("one", 2)); + } + + static class GenericType { T content; } @@ -2971,4 +3065,106 @@ public SubTypeOfGenericType convert(org.bson.Document source) { return target; } } + + @WritingConverter + static class TypeImplementingMapToDocumentConverter implements Converter { + + @Nullable + @Override + public org.bson.Document convert(TypeImplementingMap source) { + return new org.bson.Document("1st", source.val1).append("2nd", source.val2); + } + } + + @ReadingConverter + static class DocumentToTypeImplementingMapConverter implements Converter { + + @Nullable + @Override + public TypeImplementingMap convert(org.bson.Document source) { + return new TypeImplementingMap(source.getString("1st"), source.getInteger("2nd")); + } + } + + static class TypeWrappingTypeImplementingMap { + + String id; + TypeImplementingMap typeImplementingMap; + } + + @EqualsAndHashCode + static class TypeImplementingMap implements Map { + + String val1; + int val2; + + public TypeImplementingMap(String val1, int val2) { + this.val1 = val1; + this.val2 = val2; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public String get(Object key) { + return null; + } + + @Nullable + @Override + public String put(String key, String value) { + return null; + } + + @Override + public String remove(Object key) { + return null; + } + + @Override + public void putAll(@NonNull Map m) { + + } + + @Override + public void clear() { + + } + + @NonNull + @Override + public Set keySet() { + return null; + } + + @NonNull + @Override + public Collection values() { + return null; + } + + @NonNull + @Override + public Set> entrySet() { + return null; + } + } } From 2b715c54d3749adf4df0d9020343393eb31afbc0 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Jun 2021 11:32:15 +0200 Subject: [PATCH 0432/1381] Polishing. Reformat code. See #3660. Original pull request: #3662. --- .../core/convert/MappingMongoConverter.java | 35 ++++++++++--------- .../MappingMongoConverterUnitTests.java | 28 +++++++-------- 2 files changed, 32 insertions(+), 31 deletions(-) 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 d41decf3ed..bcb9575b92 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 @@ -171,8 +171,8 @@ protected ConversionContext getConversionContext(ObjectPath path) { Assert.notNull(path, "ObjectPath must not be null"); - return new ConversionContext(conversions, path, this::readDocument, this::readCollectionOrArray, this::readMap, this::readDBRef, - this::getPotentiallyConvertedSimpleRead); + return new ConversionContext(conversions, path, this::readDocument, this::readCollectionOrArray, this::readMap, + this::readDBRef, this::getPotentiallyConvertedSimpleRead); } /** @@ -527,7 +527,8 @@ private void readAssociation(Association association, P return; } - if (property.isDocumentReference() || (!property.isDbReference() && property.findAnnotation(Reference.class) != null)) { + if (property.isDocumentReference() + || (!property.isDbReference() && property.findAnnotation(Reference.class) != null)) { // quite unusual but sounds like worth having? @@ -595,13 +596,13 @@ public DocumentPointer toDocumentPointer(Object source, @Nullable MongoPersisten Assert.notNull(referringProperty, "Cannot create DocumentReference. The referringProperty must not be null!"); - if (referringProperty.isDbReference()) { - return () -> toDBRef(source, referringProperty); - } + if (referringProperty.isDbReference()) { + return () -> toDBRef(source, referringProperty); + } - if (referringProperty.isDocumentReference() || referringProperty.findAnnotation(Reference.class) != null) { - return createDocumentPointer(source, referringProperty); - } + if (referringProperty.isDocumentReference() || referringProperty.findAnnotation(Reference.class) != null) { + return createDocumentPointer(source, referringProperty); + } throw new IllegalArgumentException("The referringProperty is neither a DBRef nor a document reference"); } @@ -612,7 +613,7 @@ DocumentPointer createDocumentPointer(Object source, @Nullable MongoPersisten return () -> source; } - if(source instanceof DocumentPointer) { + if (source instanceof DocumentPointer) { return (DocumentPointer) source; } @@ -622,7 +623,8 @@ DocumentPointer createDocumentPointer(Object source, @Nullable MongoPersisten } if (ClassUtils.isAssignableValue(referringProperty.getAssociationTargetType(), source)) { - return documentPointerFactory.computePointer(mappingContext, referringProperty, source, referringProperty.getActualType()); + return documentPointerFactory.computePointer(mappingContext, referringProperty, source, + referringProperty.getActualType()); } return () -> source; @@ -1978,9 +1980,10 @@ protected static class ConversionContext { private final ContainerValueConverter dbRefConverter; private final ValueConverter elementConverter; - ConversionContext(org.springframework.data.convert.CustomConversions customConversions, ObjectPath path, ContainerValueConverter documentConverter, - ContainerValueConverter> collectionConverter, ContainerValueConverter mapConverter, - ContainerValueConverter dbRefConverter, ValueConverter elementConverter) { + ConversionContext(org.springframework.data.convert.CustomConversions customConversions, ObjectPath path, + ContainerValueConverter documentConverter, ContainerValueConverter> collectionConverter, + ContainerValueConverter mapConverter, ContainerValueConverter dbRefConverter, + ValueConverter elementConverter) { this.conversions = customConversions; this.path = path; @@ -2052,8 +2055,8 @@ public ConversionContext withPath(ObjectPath currentPath) { Assert.notNull(currentPath, "ObjectPath must not be null"); - return new ConversionContext(conversions, currentPath, documentConverter, collectionConverter, mapConverter, dbRefConverter, - elementConverter); + return new ConversionContext(conversions, currentPath, documentConverter, collectionConverter, mapConverter, + dbRefConverter, elementConverter); } public ObjectPath getPath() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 441b8e3347..2009b5314b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -30,7 +30,6 @@ import java.time.temporal.ChronoUnit; import java.util.*; -import org.assertj.core.api.Assertions; import org.bson.types.Code; import org.bson.types.Decimal128; import org.bson.types.ObjectId; @@ -42,6 +41,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.factory.annotation.Value; @@ -529,7 +529,7 @@ void writesBigIntegerIdCorrectly() { } @Test - public void convertsObjectsIfNecessary() { + void convertsObjectsIfNecessary() { ObjectId id = new ObjectId(); assertThat(converter.convertToMongoType(id)).isEqualTo(id); @@ -2113,21 +2113,21 @@ void shouldAllowReadingBackDbObject() { } @Test // DATAMONGO-2479 - public void entityCallbacksAreNotSetByDefault() { - Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isNull(); + void entityCallbacksAreNotSetByDefault() { + assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isNull(); } @Test // DATAMONGO-2479 - public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { + void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { ApplicationContext ctx = new StaticApplicationContext(); converter.setApplicationContext(ctx); - Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isNotNull(); + assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isNotNull(); } @Test // DATAMONGO-2479 - public void setterForEntityCallbackOverridesContextInitializedOnes() { + void setterForEntityCallbackOverridesContextInitializedOnes() { ApplicationContext ctx = new StaticApplicationContext(); converter.setApplicationContext(ctx); @@ -2135,11 +2135,11 @@ public void setterForEntityCallbackOverridesContextInitializedOnes() { EntityCallbacks callbacks = EntityCallbacks.create(); converter.setEntityCallbacks(callbacks); - Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isSameAs(callbacks); + assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isSameAs(callbacks); } @Test // DATAMONGO-2479 - public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { + void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { EntityCallbacks callbacks = EntityCallbacks.create(); ApplicationContext ctx = new StaticApplicationContext(); @@ -2147,11 +2147,11 @@ public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallback converter.setEntityCallbacks(callbacks); converter.setApplicationContext(ctx); - Assertions.assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isSameAs(callbacks); + assertThat(ReflectionTestUtils.getField(converter, "entityCallbacks")).isSameAs(callbacks); } @Test // DATAMONGO-2479 - public void resolveDBRefMapValueShouldInvokeCallbacks() { + void resolveDBRefMapValueShouldInvokeCallbacks() { AfterConvertCallback afterConvertCallback = spy(new ReturningAfterConvertCallback()); converter.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); @@ -2168,7 +2168,7 @@ public void resolveDBRefMapValueShouldInvokeCallbacks() { } @Test // DATAMONGO-2300 - public void readAndConvertDBRefNestedByMapCorrectly() { + void readAndConvertDBRefNestedByMapCorrectly() { org.bson.Document cluster = new org.bson.Document("_id", 100L); DBRef dbRef = new DBRef("clusters", 100L); @@ -2434,7 +2434,6 @@ void shouldUseMostConcreteCustomConversionTargetOnRead() { @Test // GH-3660 void usesCustomConverterForMapTypesOnWrite() { - converter = new MappingMongoConverter(resolver, mappingContext); converter.setCustomConversions(MongoCustomConversions.create(it -> { it.registerConverter(new TypeImplementingMapToDocumentConverter()); @@ -2521,7 +2520,6 @@ void usesCustomConverterForPropertiesUsingTypesImplementingMapOnRead() { assertThat(target.typeImplementingMap).isEqualTo(new TypeImplementingMap("one", 2)); } - static class GenericType { T content; } @@ -3098,7 +3096,7 @@ static class TypeImplementingMap implements Map { String val1; int val2; - public TypeImplementingMap(String val1, int val2) { + TypeImplementingMap(String val1, int val2) { this.val1 = val1; this.val2 = val2; } From 149a703ecce3d0cb4ee8dcb8169184a2f1e801f0 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 4 May 2021 13:35:45 +0200 Subject: [PATCH 0433/1381] Fix NPE in QueryMapper when trying to apply target type on null value. Closes #3633 Original pull request: #3643. --- .../data/mongodb/core/convert/QueryMapper.java | 6 +++--- .../mongodb/core/convert/QueryMapperUnitTests.java | 11 +++++++++++ .../AbstractPersonRepositoryIntegrationTests.java | 11 +++++++++++ .../data/mongodb/repository/PersonRepository.java | 3 +++ .../json/ParameterBindingJsonReaderUnitTests.java | 7 +++++++ 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 81c1c96ddf..65f66ec4cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -756,12 +756,12 @@ protected boolean isKeyword(String candidate) { * converted one by one. * * @param documentField the field and its meta data - * @param value the actual value + * @param value the actual value. Can be {@literal null}. * @return the potentially converted target value. */ - private Object applyFieldTargetTypeHintToValue(Field documentField, Object value) { + private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) { - if (documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) { + if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) { return value; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index f7b5ec76d7..8c23b4a222 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1255,6 +1255,17 @@ void resolvesFieldNameWithUnderscoreOnNestedMappedFieldnameWithUnderscoresCorrec assertThat(document).isEqualTo(new org.bson.Document("double_underscore.renamed", new org.bson.Document("$exists", true))); } + @Test // GH-3633 + void mapsNullValueForFieldWithCustomTargetType() { + + Query query = query(where("stringAsOid").is(null)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(NonIdFieldWithObjectIdTargetType.class)); + + assertThat(document).isEqualTo(new org.bson.Document("stringAsOid", null)); + } + class WithDeepArrayNesting { List level0; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 61caa30560..d576913850 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -61,7 +61,9 @@ import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.mongodb.repository.SampleEvaluationContextExtension.SampleSecurityContextHolder; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; @@ -1435,6 +1437,15 @@ void annotatedQueryShouldAllowAggregationInProjection() { assertThat(target.getFirstname()).isEqualTo(alicia.getFirstname().toUpperCase()); } + @Test // GH-3633 + void annotatedQueryWithNullEqualityCheckShouldWork() { + + operations.updateFirst(Query.query(Criteria.where("id").is(dave.getId())), Update.update("age", null), Person.class); + + Person byQueryWithNullEqualityCheck = repository.findByQueryWithNullEqualityCheck(); + assertThat(byQueryWithNullEqualityCheck.getId()).isEqualTo(dave.getId()); + } + @Test // GH-3602 void executesQueryWithDocumentReferenceCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index ca382fa2ca..155cf7a7b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -417,5 +417,8 @@ Person findPersonByManyArguments(String firstname, String lastname, String email List findByUnwrappedUser(User user); + @Query("{ 'age' : null }") + Person findByQueryWithNullEqualityCheck(); + List findBySpiritAnimal(User user); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java index 72ab2b454b..1a684af164 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java @@ -383,6 +383,13 @@ void shouldParseNestedArrays() { .parse("{ 'stores.location' : { $geoWithin: { $centerSphere: [ [ 1.948516, 48.799029 ] , 0.004 ] } } }")); } + @Test // GH-3633 + void parsesNullValue() { + + Document target = parse("{ 'parent' : null }"); + assertThat(target).isEqualTo(new Document("parent", null)); + } + private static Document parse(String json, Object... args) { ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args); From efa9a2d40877f78a95e4b9314ed7ae5ff2ed23c1 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 4 May 2021 14:29:52 +0200 Subject: [PATCH 0434/1381] Add Criteria.isNullValue() as alternative to Criteria.is(null). See #3633 Original pull request: #3643. --- .../data/mongodb/core/query/Criteria.java | 37 +++++++++++++++++++ .../core/convert/QueryMapperUnitTests.java | 13 ++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index b0a1b49893..9b1e8df940 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -29,6 +29,7 @@ import java.util.stream.Collectors; import org.bson.BsonRegularExpression; +import org.bson.BsonType; import org.bson.Document; import org.bson.types.Binary; import org.springframework.data.domain.Example; @@ -188,6 +189,42 @@ public Criteria is(@Nullable Object value) { return this; } + /** + * Creates a criterion using {@literal null} equality comparison which matches documents that either contain the item + * field whose value is {@literal null} or that do not contain the item field. + *

      + * Use {@link #isNullValue()} to only query for documents that contain the field whose value is equal to + * {@link org.bson.BsonType#NULL}.
      + * Use {@link #exists(boolean)} to query for documents that do (not) contain the field. + * + * @return this. + * @see Query for Null or + * Missing Fields: Equality Filter + * @since 3.3 + */ + public Criteria isNull() { + return is(null); + } + + /** + * Creates a criterion using a {@link org.bson.BsonType} comparison which matches only documents that contain the item + * field whose value is equal to {@link org.bson.BsonType#NULL}. + *

      + * Use {@link #isNull()} to query for documents that contain the field with a {@literal null} value or do not contain the + * field at all.
      + * Use {@link #exists(boolean)} to query for documents that do (not) contain the field. + * + * @return this. + * @see Query for Null or Missing + * Fields: Type Check + * @since 3.3 + */ + public Criteria isNullValue() { + + criteria.put("$type", BsonType.NULL.getValue()); + return this; + } + private boolean lastOperatorWasNot() { return !this.criteria.isEmpty() && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1]); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 8c23b4a222..dd8dd25e8f 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1258,7 +1258,7 @@ void resolvesFieldNameWithUnderscoreOnNestedMappedFieldnameWithUnderscoresCorrec @Test // GH-3633 void mapsNullValueForFieldWithCustomTargetType() { - Query query = query(where("stringAsOid").is(null)); + Query query = query(where("stringAsOid").isNull()); org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(NonIdFieldWithObjectIdTargetType.class)); @@ -1266,6 +1266,17 @@ void mapsNullValueForFieldWithCustomTargetType() { assertThat(document).isEqualTo(new org.bson.Document("stringAsOid", null)); } + @Test // GH-3633 + void mapsNullBsonTypeForFieldWithCustomTargetType() { + + Query query = query(where("stringAsOid").isNullValue()); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(NonIdFieldWithObjectIdTargetType.class)); + + assertThat(document).isEqualTo(new org.bson.Document("stringAsOid", new org.bson.Document("$type", 10))); + } + class WithDeepArrayNesting { List level0; From a481636429fd92af83a8226c0c51ae1cbf13afe3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 9 Jun 2021 12:06:43 +0200 Subject: [PATCH 0435/1381] Polishing. Add nullability annotation. Return early on null value conversion. See #3633 Original pull request: #3643. --- .../data/mongodb/core/convert/QueryMapper.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 65f66ec4cb..5840815562 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -445,6 +445,10 @@ else if (isDocument(value)) { } } + if (value == null) { + return null; + } + if (isNestedKeyword(value)) { return getMappedKeyword(new Keyword((Bson) value), documentField.getPropertyEntity()); } @@ -711,7 +715,7 @@ public Object convertId(@Nullable Object id, Class targetType) { * @param candidate * @return */ - protected boolean isNestedKeyword(Object candidate) { + protected boolean isNestedKeyword(@Nullable Object candidate) { if (!(candidate instanceof Document)) { return false; @@ -759,6 +763,7 @@ protected boolean isKeyword(String candidate) { * @param value the actual value. Can be {@literal null}. * @return the potentially converted target value. */ + @Nullable private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) { if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) { From b1020d19baf0d61a4be8fc98aa0f09e514af0ea2 Mon Sep 17 00:00:00 2001 From: Divya Srivastava Date: Sun, 9 May 2021 16:16:43 +0530 Subject: [PATCH 0436/1381] Add an option to `@Field` annotation to include/exclude null values on write. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properties can be annotated with `@Field(write=…)` to control whether a property with a null value should be included or omitted (default) during conversion in the target Document. Closes #3407 Original pull request: #3646. --- .../core/convert/MappingMongoConverter.java | 3 +++ .../mapping/BasicMongoPersistentProperty.java | 14 +++++++++++ .../data/mongodb/core/mapping/Field.java | 25 +++++++++++++++++++ .../core/mapping/MongoPersistentProperty.java | 18 +++++++++++++ .../UnwrappedMongoPersistentProperty.java | 10 ++++++++ ...BasicMongoPersistentPropertyUnitTests.java | 13 ++++++++++ 6 files changed, 83 insertions(+) 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 bcb9575b92..86be47c558 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 @@ -744,6 +744,9 @@ private void writeProperties(Bson bson, MongoPersistentEntity entity, Persist Object value = accessor.getProperty(prop); if (value == null) { + if(!prop.isPropertyOmittableOnNull()) { + writeSimpleInternal(value, bson , prop); + } continue; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 53af00fc54..3973f802a2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -285,4 +285,18 @@ public boolean isExplicitLanguageProperty() { public boolean isTextScoreProperty() { return isAnnotationPresent(TextScore.class); } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isPropertyOmittableOnNull() + */ + public boolean isPropertyOmittableOnNull() { + org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation( + org.springframework.data.mongodb.core.mapping.Field.class); + + if ( annotation != null && annotation.write().equals(Field.Write.ALWAYS) ) { + return false; + } + return true; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java index 45e8b815fb..b2365f8d6c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java @@ -34,6 +34,21 @@ @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) public @interface Field { + /** + * Enumeration of write strategies for a field with null value.It decides whether a field with null value has to be + * written to the resulting document to be saved to the database. + */ + enum Write{ + /* + * The field will always be written to the database irrespective of null value. + */ + ALWAYS, + /* + * The field will only be written to the database if it has a non null value. + */ + NON_NULL + } + /** * The key to be used to store the field inside the document. Alias for {@link #name()}. * @@ -65,4 +80,14 @@ * @since 2.2 */ FieldType targetType() default FieldType.IMPLICIT; + + /** + * If set to {@link Write#NON_NULL} {@literal null} values will be omitted. + * Setting the value to {@link Write#ALWAYS} explicitly adds an entry for the given field + * holding {@literal null} as a value {@code 'fieldName' : null }. + *

      + * NOTE Setting the value to {@link Write#ALWAYS} may lead to increased document size. + * @return {@link Write#NON_NULL} by default. + */ + Write write() default Write.NON_NULL; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index c753f3856d..10f35435d2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -104,6 +104,24 @@ public interface MongoPersistentProperty extends PersistentProperty + * It's annotated with {@link Field.Write}. + * + * @return + * @since 1.6 + */ + boolean isPropertyOmittableOnNull(); + + /** + * Returns whether the property is to be written to the document if the value is null
      + * It's annotated with {@link omitNull}. + * + * @return + * @since 1.6 + */ + boolean isOmitNullProperty(); /** * Returns the {@link DBRef} if the property is a reference. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java index f8218171c5..3d7de5d094 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java @@ -92,6 +92,11 @@ public boolean isExplicitLanguageProperty() { public boolean isTextScoreProperty() { return delegate.isTextScoreProperty(); } + + @Override + public boolean isOmitNullProperty() { + return delegate.isOmitNullProperty(); + } @Override @Nullable @@ -315,4 +320,9 @@ public Class getAssociationTargetType() { public PersistentPropertyAccessor getAccessorForOwner(T owner) { return delegate.getAccessorForOwner(owner); } + + @Override + public boolean isPropertyOmittableOnNull() { + return delegate.isPropertyOmittableOnNull(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 3fb4f59084..69f9cb6613 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -146,6 +146,13 @@ public void shouldDetectTextScorePropertyCorrectly() { assertThat(property.isTextScoreProperty()).isTrue(); } + @Test // DATAMONGO-2551 + public void shouldDetectOmittableOnNullPropertyCorrectly() { + + MongoPersistentProperty property = getPropertyFor(DocumentWithOmittableOnNullProperty.class, "write"); + assertThat(property.isPropertyOmittableOnNull()).isTrue(); + } + @Test // DATAMONGO-976 public void shouldDetectTextScoreAsReadOnlyProperty() { @@ -297,6 +304,12 @@ static class DocumentWithTextScoreProperty { @TextScore Float score; } + static class DocumentWithOmittableOnNullProperty { + + @org.springframework.data.mongodb.core.mapping.Field("write") org.springframework.data.mongodb.core.mapping.Field.Write write; + + } + static class DocumentWithExplicitlyRenamedIdProperty { @org.springframework.data.mongodb.core.mapping.Field("id") String id; From c217618d9dfb29d1de45e7767844cff2d668d956 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 14 Jun 2021 09:30:08 +0200 Subject: [PATCH 0437/1381] Polishing. Reorder methods and types. Rename MongoPersistentProperty.isOmitNullProperty to writeNullValues. Adapt caching MongoPersistentProperty and add tests. Tweak Javadoc wording, add author and since tags. See #3407 Original pull request: #3646. --- .../core/convert/MappingMongoConverter.java | 20 +++-- .../mapping/BasicMongoPersistentProperty.java | 27 +++--- .../CachingMongoPersistentProperty.java | 15 ++++ .../data/mongodb/core/mapping/Field.java | 44 ++++++---- .../core/mapping/MongoPersistentProperty.java | 28 +++--- .../UnwrappedMongoPersistentProperty.java | 14 ++- .../data/mongodb/core/MongoTemplateTests.java | 88 ++++++++++++++++++- .../mongodb/core/MongoTemplateUnitTests.java | 6 +- .../MappingMongoConverterUnitTests.java | 28 ++++++ ...BasicMongoPersistentPropertyUnitTests.java | 73 ++++++++------- src/main/asciidoc/new-features.adoc | 1 + 11 files changed, 242 insertions(+), 102 deletions(-) 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 86be47c558..732e8c9a51 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 @@ -103,6 +103,7 @@ * @author Mark Paluch * @author Roman Puchkovskiy * @author Heesu Jung + * @author Divya Srivastava */ public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware { @@ -737,6 +738,7 @@ private void writeProperties(Bson bson, MongoPersistentEntity entity, Persist continue; } if (prop.isAssociation()) { + writeAssociation(prop.getRequiredAssociation(), accessor, dbObjectAccessor); continue; } @@ -744,13 +746,10 @@ private void writeProperties(Bson bson, MongoPersistentEntity entity, Persist Object value = accessor.getProperty(prop); if (value == null) { - if(!prop.isPropertyOmittableOnNull()) { - writeSimpleInternal(value, bson , prop); + if (prop.writeNullValues()) { + dbObjectAccessor.put(prop, null); } - continue; - } - - if (!conversions.isSimpleType(value.getClass())) { + } else if (!conversions.isSimpleType(value.getClass())) { writePropertyInternal(value, dbObjectAccessor, prop); } else { writeSimpleInternal(value, bson, prop); @@ -763,7 +762,14 @@ private void writeAssociation(Association association, MongoPersistentProperty inverseProp = association.getInverse(); - writePropertyInternal(accessor.getProperty(inverseProp), dbObjectAccessor, inverseProp); + Object value = accessor.getProperty(inverseProp); + + if (value == null && !inverseProp.isUnwrapped() && inverseProp.writeNullValues()) { + dbObjectAccessor.put(inverseProp, null); + return; + } + + writePropertyInternal(value, dbObjectAccessor, inverseProp); } @SuppressWarnings({ "unchecked" }) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 3973f802a2..87eb56b732 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -41,6 +41,7 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author Divya Srivastava */ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty implements MongoPersistentProperty { @@ -214,6 +215,19 @@ public int getFieldOrder() { return annotation != null ? annotation.order() : Integer.MAX_VALUE; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#skipNullValues() + */ + @Override + public boolean writeNullValues() { + + org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation( + org.springframework.data.mongodb.core.mapping.Field.class); + + return annotation != null && annotation.write() == Field.Write.ALWAYS; + } + /* * (non-Javadoc) * @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation() @@ -286,17 +300,4 @@ public boolean isTextScoreProperty() { return isAnnotationPresent(TextScore.class); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isPropertyOmittableOnNull() - */ - public boolean isPropertyOmittableOnNull() { - org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation( - org.springframework.data.mongodb.core.mapping.Field.class); - - if ( annotation != null && annotation.write().equals(Field.Write.ALWAYS) ) { - return false; - } - return true; - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java index 7af678541b..53a501e068 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java @@ -33,6 +33,7 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty private boolean dbRefResolved; private @Nullable DBRef dbref; private @Nullable String fieldName; + private @Nullable Boolean writeNullValues; private @Nullable Class fieldType; private @Nullable Boolean usePropertyAccess; private @Nullable Boolean isTransient; @@ -90,6 +91,20 @@ public String getFieldName() { return this.fieldName; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty#skipNullValues() + */ + @Override + public boolean writeNullValues() { + + if (this.writeNullValues == null) { + this.writeNullValues = super.writeNullValues(); + } + + return this.writeNullValues; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.BasicMongoPersistentProperty#getFieldType() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java index b2365f8d6c..b606cf15b9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Field.java @@ -28,27 +28,13 @@ * * @author Oliver Gierke * @author Christoph Strobl + * @author Divya Srivastava */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) public @interface Field { - /** - * Enumeration of write strategies for a field with null value.It decides whether a field with null value has to be - * written to the resulting document to be saved to the database. - */ - enum Write{ - /* - * The field will always be written to the database irrespective of null value. - */ - ALWAYS, - /* - * The field will only be written to the database if it has a non null value. - */ - NON_NULL - } - /** * The key to be used to store the field inside the document. Alias for {@link #name()}. * @@ -82,12 +68,32 @@ enum Write{ FieldType targetType() default FieldType.IMPLICIT; /** - * If set to {@link Write#NON_NULL} {@literal null} values will be omitted. - * Setting the value to {@link Write#ALWAYS} explicitly adds an entry for the given field - * holding {@literal null} as a value {@code 'fieldName' : null }. + * Write rules when to include a property value upon conversion. If set to {@link Write#NON_NULL} (default) + * {@literal null} values are not written to the target {@code Document}. Setting the value to {@link Write#ALWAYS} + * explicitly adds an entry for the given field holding {@literal null} as a value {@code 'fieldName' : null }. *

      - * NOTE Setting the value to {@link Write#ALWAYS} may lead to increased document size. + * NOTESetting the value to {@link Write#ALWAYS} may lead to increased document size. + * * @return {@link Write#NON_NULL} by default. + * @since 3.3 */ Write write() default Write.NON_NULL; + + /** + * Enumeration of write strategies to define when a property is included for write conversion. + * + * @since 3.3 + */ + enum Write { + + /** + * Value that indicates that property is to be always included, independent of value of the property. + */ + ALWAYS, + + /** + * Value that indicates that only properties with non-{@literal null} values are to be included. + */ + NON_NULL + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index 10f35435d2..2bd387d74c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -28,6 +28,7 @@ * @author Patryk Wasik * @author Thomas Darimont * @author Christoph Strobl + * @author Divya Srivastava */ public interface MongoPersistentProperty extends PersistentProperty { @@ -54,6 +55,15 @@ public interface MongoPersistentProperty extends PersistentProperty - * It's annotated with {@link Field.Write}. - * - * @return - * @since 1.6 - */ - boolean isPropertyOmittableOnNull(); - - /** - * Returns whether the property is to be written to the document if the value is null
      - * It's annotated with {@link omitNull}. - * - * @return - * @since 1.6 - */ - boolean isOmitNullProperty(); /** * Returns the {@link DBRef} if the property is a reference. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java index 3d7de5d094..6d4b163d22 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java @@ -63,6 +63,11 @@ public int getFieldOrder() { return delegate.getFieldOrder(); } + @Override + public boolean writeNullValues() { + return delegate.writeNullValues(); + } + @Override public boolean isDbReference() { return delegate.isDbReference(); @@ -92,11 +97,6 @@ public boolean isExplicitLanguageProperty() { public boolean isTextScoreProperty() { return delegate.isTextScoreProperty(); } - - @Override - public boolean isOmitNullProperty() { - return delegate.isOmitNullProperty(); - } @Override @Nullable @@ -321,8 +321,4 @@ public PersistentPropertyAccessor getAccessorForOwner(T owner) { return delegate.getAccessorForOwner(owner); } - @Override - public boolean isPropertyOmittableOnNull() { - return delegate.isPropertyOmittableOnNull(); - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index b18e1066f5..f5521008f8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -24,6 +24,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.Value; import lombok.With; @@ -1692,7 +1693,7 @@ public void countAndFindWithoutTypeInformation() { assertThat(template.count(query, collectionName)).isEqualTo(1L); } - @Test // DATAMONGO-571 + @Test // DATAMONGO-571, GH-3407 public void nullsPropertiesForVersionObjectUpdates() { VersionedPerson person = new VersionedPerson(); @@ -1702,11 +1703,17 @@ public void nullsPropertiesForVersionObjectUpdates() { template.save(person); assertThat(person.id).isNotNull(); + person.firstname = null; person.lastname = null; template.save(person); person = template.findOne(query(where("id").is(person.id)), VersionedPerson.class); + assertThat(person.firstname).isNull(); assertThat(person.lastname).isNull(); + + org.bson.Document document = template.findOne(query(where("_id").is(person.id)), org.bson.Document.class, + "versionedPerson"); + assertThat(document).doesNotContainKey("firstname").containsEntry("lastname", null); } @Test // DATAMONGO-571 @@ -3703,6 +3710,64 @@ public void sortOnIdFieldWithExplicitTypeShouldWork() { assertThat(template.find(new BasicQuery("{}").with(Sort.by("id")), WithIdAndFieldAnnotation.class)).isNotEmpty(); } + @Test // GH-3407 + void shouldWriteSubdocumentWithNullCorrectly() { + + template.dropCollection(WithSubdocument.class); + + WithSubdocument doc = new WithSubdocument(); + SubdocumentWithWriteNull subdoc = new SubdocumentWithWriteNull("Walter", "White"); + doc.subdocument = subdoc; + + template.save(doc); + + org.bson.Document loaded = template.findById(doc.id, org.bson.Document.class, "withSubdocument"); + + assertThat(loaded.get("subdocument", org.bson.Document.class)).hasSize(3).containsEntry("firstname", "Walter") + .containsEntry("nickname", null); + } + + @Test // GH-3407 + void shouldUpdateSubdocumentWithNullCorrectly() { + + template.dropCollection(WithSubdocument.class); + + WithSubdocument doc = new WithSubdocument(); + SubdocumentWithWriteNull subdoc = new SubdocumentWithWriteNull("Walter", "White"); + subdoc.nickname = "Heisenberg"; + doc.subdocument = subdoc; + + template.save(doc); + + String id = doc.id; + + doc.id = null; + subdoc.nickname = null; + template.update(WithSubdocument.class).replaceWith(doc).findAndReplaceValue(); + + org.bson.Document loaded = template.findById(id, org.bson.Document.class, "withSubdocument"); + + assertThat(loaded.get("subdocument", org.bson.Document.class)).hasSize(3).containsEntry("firstname", "Walter") + .containsEntry("nickname", null); + } + + @Test // GH-3407 + void shouldFindSubdocumentWithNullCorrectly() { + + template.dropCollection(WithSubdocument.class); + + WithSubdocument doc = new WithSubdocument(); + SubdocumentWithWriteNull subdoc = new SubdocumentWithWriteNull("Walter", "White"); + doc.subdocument = subdoc; + + template.save(doc); + + org.bson.Document loaded = template.findOne(query(where("subdocument").is(subdoc)), org.bson.Document.class, + "withSubdocument"); + + assertThat(loaded).isNotNull(); + } + private AtomicReference createAfterSaveReference() { AtomicReference saved = new AtomicReference<>(); @@ -4020,7 +4085,8 @@ public int hashCode() { static class VersionedPerson { @Version Long version; - String id, firstname, lastname; + String id, firstname; + @Field(write = Field.Write.ALWAYS) String lastname; } static class TypeWithFieldAnnotation { @@ -4247,4 +4313,22 @@ static class WithIdAndFieldAnnotation { String value; } + + @Data + static class WithSubdocument { + + @Id // + @Field(name = "_id") // + String id; + SubdocumentWithWriteNull subdocument; + } + + @Data + @RequiredArgsConstructor + static class SubdocumentWithWriteNull { + + final String firstname, lastname; + + @Field(write = Field.Write.ALWAYS) String nickname; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index f8170889b6..c3ee9b32ff 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1139,7 +1139,7 @@ void geoNearShouldMapGeoJsonPointCorrectly() { .containsEntry("$geoNear.near.coordinates.[1]", 2D); } - @Test // DATAMONGO-2155 + @Test // DATAMONGO-2155, GH-3407 void saveVersionedEntityShouldCallUpdateCorrectly() { when(updateResult.getModifiedCount()).thenReturn(1L); @@ -1157,7 +1157,7 @@ void saveVersionedEntityShouldCallUpdateCorrectly() { assertThat(queryCaptor.getValue()).isEqualTo(new Document("_id", 1).append("version", 10)); assertThat(updateCaptor.getValue()) - .isEqualTo(new Document("version", 11).append("_class", VersionedEntity.class.getName())); + .isEqualTo(new Document("version", 11).append("_class", VersionedEntity.class.getName()).append("name", null)); } @Test // DATAMONGO-1783 @@ -2273,6 +2273,8 @@ static class VersionedEntity { @Id Integer id; @Version Integer version; + + @Field(write = Field.Write.ALWAYS) String name; } enum MyConverter implements Converter { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 2009b5314b..0361571414 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -2520,6 +2520,18 @@ void usesCustomConverterForPropertiesUsingTypesImplementingMapOnRead() { assertThat(target.typeImplementingMap).isEqualTo(new TypeImplementingMap("one", 2)); } + @Test // GH-3407 + void shouldWriteNullPropertyCorrectly() { + + WithFieldWrite fieldWrite = new WithFieldWrite(); + + org.bson.Document document = new org.bson.Document(); + converter.write(fieldWrite, document); + + assertThat(document).containsEntry("writeAlways", null).doesNotContainKey("writeNonNull"); + assertThat(document).containsEntry("writeAlwaysPerson", null).doesNotContainKey("writeNonNullPerson"); + } + static class GenericType { T content; } @@ -3165,4 +3177,20 @@ public Set> entrySet() { return null; } } + + static class WithFieldWrite { + + @org.springframework.data.mongodb.core.mapping.Field( + write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Integer writeNonNull; + + @org.springframework.data.mongodb.core.mapping.Field( + write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Integer writeAlways; + + @org.springframework.data.mongodb.core.mapping.DBRef @org.springframework.data.mongodb.core.mapping.Field( + write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPerson; + + @org.springframework.data.mongodb.core.mapping.DBRef @org.springframework.data.mongodb.core.mapping.Field( + write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPerson; + + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 69f9cb6613..bbcb8dada0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -48,25 +48,26 @@ * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch + * @author Divya Srivastava */ public class BasicMongoPersistentPropertyUnitTests { - MongoPersistentEntity entity; + private MongoPersistentEntity entity; @BeforeEach - public void setup() { + void setup() { entity = new BasicMongoPersistentEntity<>(ClassTypeInformation.from(Person.class)); } @Test - public void usesAnnotatedFieldName() { + void usesAnnotatedFieldName() { Field field = ReflectionUtils.findField(Person.class, "firstname"); assertThat(getPropertyFor(field).getFieldName()).isEqualTo("foo"); } @Test - public void returns_IdForIdProperty() { + void returns_IdForIdProperty() { Field field = ReflectionUtils.findField(Person.class, "id"); MongoPersistentProperty property = getPropertyFor(field); assertThat(property.isIdProperty()).isTrue(); @@ -74,19 +75,19 @@ public void returns_IdForIdProperty() { } @Test - public void returnsPropertyNameForUnannotatedProperties() { + void returnsPropertyNameForUnannotatedProperties() { Field field = ReflectionUtils.findField(Person.class, "lastname"); assertThat(getPropertyFor(field).getFieldName()).isEqualTo("lastname"); } @Test - public void preventsNegativeOrder() { + void preventsNegativeOrder() { getPropertyFor(ReflectionUtils.findField(Person.class, "ssn")); } @Test // DATAMONGO-553 - public void usesPropertyAccessForThrowableCause() { + void usesPropertyAccessForThrowableCause() { BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity<>( ClassTypeInformation.from(Throwable.class)); @@ -96,7 +97,7 @@ public void usesPropertyAccessForThrowableCause() { } @Test // DATAMONGO-607 - public void usesCustomFieldNamingStrategyByDefault() throws Exception { + void usesCustomFieldNamingStrategyByDefault() throws Exception { ClassTypeInformation type = ClassTypeInformation.from(Person.class); Field field = ReflectionUtils.findField(Person.class, "lastname"); @@ -113,7 +114,7 @@ public void usesCustomFieldNamingStrategyByDefault() throws Exception { } @Test // DATAMONGO-607 - public void rejectsInvalidValueReturnedByFieldNamingStrategy() { + void rejectsInvalidValueReturnedByFieldNamingStrategy() { ClassTypeInformation type = ClassTypeInformation.from(Person.class); Field field = ReflectionUtils.findField(Person.class, "lastname"); @@ -126,49 +127,42 @@ public void rejectsInvalidValueReturnedByFieldNamingStrategy() { } @Test // DATAMONGO-937 - public void shouldDetectAnnotatedLanguagePropertyCorrectly() { + void shouldDetectAnnotatedLanguagePropertyCorrectly() { MongoPersistentProperty property = getPropertyFor(DocumentWithLanguageProperty.class, "lang"); assertThat(property.isLanguageProperty()).isTrue(); } @Test // DATAMONGO-937 - public void shouldDetectImplicitLanguagePropertyCorrectly() { + void shouldDetectImplicitLanguagePropertyCorrectly() { MongoPersistentProperty property = getPropertyFor(DocumentWithImplicitLanguageProperty.class, "language"); assertThat(property.isLanguageProperty()).isTrue(); } @Test // DATAMONGO-976 - public void shouldDetectTextScorePropertyCorrectly() { + void shouldDetectTextScorePropertyCorrectly() { MongoPersistentProperty property = getPropertyFor(DocumentWithTextScoreProperty.class, "score"); assertThat(property.isTextScoreProperty()).isTrue(); } - @Test // DATAMONGO-2551 - public void shouldDetectOmittableOnNullPropertyCorrectly() { - - MongoPersistentProperty property = getPropertyFor(DocumentWithOmittableOnNullProperty.class, "write"); - assertThat(property.isPropertyOmittableOnNull()).isTrue(); - } - @Test // DATAMONGO-976 - public void shouldDetectTextScoreAsReadOnlyProperty() { + void shouldDetectTextScoreAsReadOnlyProperty() { MongoPersistentProperty property = getPropertyFor(DocumentWithTextScoreProperty.class, "score"); assertThat(property.isWritable()).isFalse(); } @Test // DATAMONGO-1050 - public void shouldNotConsiderExplicitlyNameFieldAsIdProperty() { + void shouldNotConsiderExplicitlyNameFieldAsIdProperty() { MongoPersistentProperty property = getPropertyFor(DocumentWithExplicitlyRenamedIdProperty.class, "id"); assertThat(property.isIdProperty()).isFalse(); } @Test // DATAMONGO-1050 - public void shouldConsiderPropertyAsIdWhenExplicitlyAnnotatedWithIdEvenWhenExplicitlyNamePresent() { + void shouldConsiderPropertyAsIdWhenExplicitlyAnnotatedWithIdEvenWhenExplicitlyNamePresent() { MongoPersistentProperty property = getPropertyFor(DocumentWithExplicitlyRenamedIdPropertyHavingIdAnnotation.class, "id"); @@ -176,7 +170,7 @@ public void shouldConsiderPropertyAsIdWhenExplicitlyAnnotatedWithIdEvenWhenExpli } @Test // DATAMONGO-1373 - public void shouldConsiderComposedAnnotationsForIdField() { + void shouldConsiderComposedAnnotationsForIdField() { MongoPersistentProperty property = getPropertyFor(DocumentWithComposedAnnotations.class, "myId"); assertThat(property.isIdProperty()).isTrue(); @@ -184,14 +178,14 @@ public void shouldConsiderComposedAnnotationsForIdField() { } @Test // DATAMONGO-1373 - public void shouldConsiderComposedAnnotationsForFields() { + void shouldConsiderComposedAnnotationsForFields() { MongoPersistentProperty property = getPropertyFor(DocumentWithComposedAnnotations.class, "myField"); assertThat(property.getFieldName()).isEqualTo("myField"); } @Test // DATAMONGO-1737 - public void honorsFieldOrderWhenIteratingOverProperties() { + void honorsFieldOrderWhenIteratingOverProperties() { MongoMappingContext context = new MongoMappingContext(); MongoPersistentEntity entity = context.getPersistentEntity(Sample.class); @@ -203,36 +197,45 @@ public void honorsFieldOrderWhenIteratingOverProperties() { assertThat(properties).containsExactly("first", "second", "third"); } + @Test // GH-3407 + void shouldDetectWritability() { + + assertThat(getPropertyFor(WithFieldWrite.class, "fieldWithDefaults").writeNullValues()).isFalse(); + assertThat(getPropertyFor(WithFieldWrite.class, "fieldWithField").writeNullValues()).isFalse(); + assertThat(getPropertyFor(WithFieldWrite.class, "writeNonNull").writeNullValues()).isFalse(); + assertThat(getPropertyFor(WithFieldWrite.class, "writeAlways").writeNullValues()).isTrue(); + } + @Test // DATAMONGO-1798 - public void fieldTypeShouldReturnActualTypeForNonIdProperties() { + void fieldTypeShouldReturnActualTypeForNonIdProperties() { MongoPersistentProperty property = getPropertyFor(Person.class, "lastname"); assertThat(property.getFieldType()).isEqualTo(String.class); } @Test // DATAMONGO-1798 - public void fieldTypeShouldBeObjectIdForPropertiesAnnotatedWithCommonsId() { + void fieldTypeShouldBeObjectIdForPropertiesAnnotatedWithCommonsId() { MongoPersistentProperty property = getPropertyFor(Person.class, "id"); assertThat(property.getFieldType()).isEqualTo(ObjectId.class); } @Test // DATAMONGO-1798 - public void fieldTypeShouldBeImplicitForPropertiesAnnotatedWithMongoId() { + void fieldTypeShouldBeImplicitForPropertiesAnnotatedWithMongoId() { MongoPersistentProperty property = getPropertyFor(WithStringMongoId.class, "id"); assertThat(property.getFieldType()).isEqualTo(String.class); } @Test // DATAMONGO-1798 - public void fieldTypeShouldBeObjectIdForPropertiesAnnotatedWithMongoIdAndTargetTypeObjectId() { + void fieldTypeShouldBeObjectIdForPropertiesAnnotatedWithMongoIdAndTargetTypeObjectId() { MongoPersistentProperty property = getPropertyFor(WithStringMongoIdMappedToObjectId.class, "id"); assertThat(property.getFieldType()).isEqualTo(ObjectId.class); } @Test // DATAMONGO-2460 - public void fieldTypeShouldBeDocumentForPropertiesAnnotatedIdWhenAComplexTypeAndFieldTypeImplicit() { + void fieldTypeShouldBeDocumentForPropertiesAnnotatedIdWhenAComplexTypeAndFieldTypeImplicit() { MongoPersistentProperty property = getPropertyFor(WithComplexId.class, "id"); assertThat(property.getFieldType()).isEqualTo(Document.class); @@ -304,9 +307,15 @@ static class DocumentWithTextScoreProperty { @TextScore Float score; } - static class DocumentWithOmittableOnNullProperty { + static class WithFieldWrite { + + int fieldWithDefaults; + @org.springframework.data.mongodb.core.mapping.Field int fieldWithField; + @org.springframework.data.mongodb.core.mapping.Field( + write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Integer writeNonNull; - @org.springframework.data.mongodb.core.mapping.Field("write") org.springframework.data.mongodb.core.mapping.Field.Write write; + @org.springframework.data.mongodb.core.mapping.Field( + write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Integer writeAlways; } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index eac49f37bc..a74594bff0 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,6 +5,7 @@ == What's New in Spring Data MongoDB 3.3 * Extended support for <> entities. +* Include/exclude `null` properties on write to `Document` through `@Field(write=…)`. [[new-features.3.2]] == What's New in Spring Data MongoDB 3.2 From 98fe043b95c524ec5b6603b34268b474dd9107b3 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 17 Jun 2021 09:41:46 +0200 Subject: [PATCH 0438/1381] Directly import JSR305 jar. Closes #3672 --- spring-data-mongodb/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index c1efaea420..1f157e75bc 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -87,6 +87,13 @@ true + + com.google.code.findbugs + jsr305 + 3.0.2 + true + + From 3872b379cd9d88cc62b76ddae0d2f45219445f66 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 26 Apr 2021 06:09:09 +0200 Subject: [PATCH 0439/1381] Fix $or / $nor keyword mapping in query mapper. This commit fixes an issue with the pattern used for detecting $or / $nor which also matched other keywords like $floor. Closes: #3635 Original pull request: #3637. --- .../data/mongodb/core/convert/QueryMapper.java | 3 +-- .../data/mongodb/core/convert/QueryMapperUnitTests.java | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 5840815562..0127216e5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -797,7 +797,6 @@ private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Ob */ static class Keyword { - private static final String N_OR_PATTERN = "\\$.*or"; private static final Set NON_DBREF_CONVERTING_KEYWORDS = new HashSet<>( Arrays.asList("$", "$size", "$slice", "$gt", "$lt")); @@ -828,7 +827,7 @@ public boolean isExists() { } public boolean isOrOrNor() { - return key.matches(N_OR_PATTERN); + return key.equalsIgnoreCase("$or") || key.equalsIgnoreCase("$nor"); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index dd8dd25e8f..166c602be9 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1277,6 +1277,14 @@ void mapsNullBsonTypeForFieldWithCustomTargetType() { assertThat(document).isEqualTo(new org.bson.Document("stringAsOid", new org.bson.Document("$type", 10))); } + @Test // GH-3635 + void $floorKeywordDoesNotMatch$or$norPattern() { + + Query query = new BasicQuery(" { $expr: { $gt: [ \"$spent\" , { $floor : \"$budget\" } ] } }"); + assertThatNoException() + .isThrownBy(() -> mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(Foo.class))); + } + class WithDeepArrayNesting { List level0; From a1c165921d578598a6209e76b02961529cfd0170 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 31 May 2021 10:22:03 +0200 Subject: [PATCH 0440/1381] Fix query mapper path resolution for types considered simple ones. spring-projects/spring-data-commons#2293 changed how PersistentProperty paths get resolved and considers potentially registered converters for those, which made the path resolution fail in during the query mapping process. This commit makes sure to capture the according exception and continue with the given user input. Fixes: #3659 Original pull request: #3661. --- .../mongodb/core/convert/QueryMapper.java | 59 +++++++++++++------ .../core/convert/QueryMapperUnitTests.java | 51 +++++++++++++--- 2 files changed, 83 insertions(+), 27 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 0127216e5c..b619779590 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -19,11 +19,14 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.bson.BsonValue; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Reference; @@ -69,6 +72,8 @@ */ public class QueryMapper { + protected static final Logger LOGGER = LoggerFactory.getLogger(QueryMapper.class); + private static final List DEFAULT_ID_NAMES = Arrays.asList("id", "_id"); private static final Document META_TEXT_SCORE = new Document("$meta", "textScore"); static final ClassTypeInformation NESTED_DOCUMENT = ClassTypeInformation.from(NestedDocument.class); @@ -677,7 +682,8 @@ private Object createReferenceFor(Object source, MongoPersistentProperty propert return (DBRef) source; } - if(property != null && (property.isDocumentReference() || (!property.isDbReference() && property.findAnnotation(Reference.class) != null))) { + if (property != null && (property.isDocumentReference() + || (!property.isDbReference() && property.findAnnotation(Reference.class) != null))) { return converter.toDocumentPointer(source, property).getPointer(); } @@ -1178,8 +1184,8 @@ private PersistentPropertyPath getPath(String pathExpre removePlaceholders(DOT_POSITIONAL_PATTERN, pathExpression)); if (sourceProperty != null && sourceProperty.getOwner().equals(entity)) { - return mappingContext - .getPersistentPropertyPath(PropertyPath.from(Pattern.quote(sourceProperty.getName()), entity.getTypeInformation())); + return mappingContext.getPersistentPropertyPath( + PropertyPath.from(Pattern.quote(sourceProperty.getName()), entity.getTypeInformation())); } PropertyPath path = forName(rawPath); @@ -1187,29 +1193,46 @@ private PersistentPropertyPath getPath(String pathExpre return null; } - try { + PersistentPropertyPath propertyPath = tryToResolvePersistentPropertyPath(path); - PersistentPropertyPath propertyPath = mappingContext.getPersistentPropertyPath(path); + if (propertyPath == null) { - Iterator iterator = propertyPath.iterator(); - boolean associationDetected = false; + if (QueryMapper.LOGGER.isInfoEnabled()) { + + String types = StringUtils.collectionToDelimitedString( + path.stream().map(it -> it.getType().getSimpleName()).collect(Collectors.toList()), " -> "); + QueryMapper.LOGGER.info( + "Could not map '{}'. Maybe a fragment in '{}' is considered a simple type. Mapper continues with {}.", + path, types, pathExpression); + } + return null; + } - while (iterator.hasNext()) { + Iterator iterator = propertyPath.iterator(); + boolean associationDetected = false; - MongoPersistentProperty property = iterator.next(); + while (iterator.hasNext()) { - if (property.isAssociation()) { - associationDetected = true; - continue; - } + MongoPersistentProperty property = iterator.next(); - if (associationDetected && !property.isIdProperty()) { - throw new MappingException(String.format(INVALID_ASSOCIATION_REFERENCE, pathExpression)); - } + if (property.isAssociation()) { + associationDetected = true; + continue; } - return propertyPath; - } catch (InvalidPersistentPropertyPath e) { + if (associationDetected && !property.isIdProperty()) { + throw new MappingException(String.format(INVALID_ASSOCIATION_REFERENCE, pathExpression)); + } + } + + return propertyPath; + } + + private PersistentPropertyPath tryToResolvePersistentPropertyPath(PropertyPath path) { + + try { + return mappingContext.getPersistentPropertyPath(path); + } catch (MappingException e) { return null; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 166c602be9..e2a65d5322 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Optional; +import lombok.Data; import org.bson.conversions.Bson; import org.bson.types.Code; import org.bson.types.ObjectId; @@ -35,9 +36,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; - +import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; +import org.springframework.data.convert.WritingConverter; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.geo.Point; @@ -52,6 +54,7 @@ import org.springframework.data.mongodb.core.mapping.FieldType; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.mapping.Unwrapped; import org.springframework.data.mongodb.core.query.BasicQuery; @@ -1285,6 +1288,26 @@ void mapsNullBsonTypeForFieldWithCustomTargetType() { .isThrownBy(() -> mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(Foo.class))); } + @Test // GH-3659 + void allowsUsingFieldPathsForPropertiesHavingCustomConversionRegistered() { + + Query query = query(where("address.street").is("1007 Mountain Drive")); + + MongoCustomConversions mongoCustomConversions = new MongoCustomConversions(Collections.singletonList(new MyAddressToDocumentConverter())); + + this.context = new MongoMappingContext(); + this.context.setSimpleTypeHolder(mongoCustomConversions.getSimpleTypeHolder()); + this.context.afterPropertiesSet(); + + this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); + this.converter.setCustomConversions(mongoCustomConversions); + this.converter.afterPropertiesSet(); + + this.mapper = new QueryMapper(converter); + + assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class))).isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive")); + } + class WithDeepArrayNesting { List level0; @@ -1516,17 +1539,27 @@ static class WithPropertyUsingUnderscoreInName { String renamed_fieldname_with_underscores; } - static class WithDocumentReferences { + @Document + static class Customer { - @DocumentReference - Sample sample; + @Id + private ObjectId id; + private String name; + private MyAddress address; + } - @DocumentReference - SimpeEntityWithoutId noId; + static class MyAddress { + private String street; + } - @DocumentReference(lookup = "{ 'stringProperty' : ?#{stringProperty} }") - SimpeEntityWithoutId noIdButLookupQuery; + @WritingConverter + public static class MyAddressToDocumentConverter implements Converter { + @Override + public org.bson.Document convert(MyAddress address) { + org.bson.Document doc = new org.bson.Document(); + doc.put("street", address.street); + return doc; + } } - } From 73a0f0493358dae7040ff3613524ca1450e2a585 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 1 Jun 2021 09:25:15 +0200 Subject: [PATCH 0441/1381] Polishing. Fix typo in class name and make sure MongoTestTemplate uses the configured simple types. Remove superfluous junit extension. See: #3659 Original pull request: #3661. --- .../data/mongodb/core/convert/QueryMapper.java | 1 + .../mongodb/core/convert/QueryMapperUnitTests.java | 10 +++------- .../test/util/MongoTestTemplateConfiguration.java | 3 +++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index b619779590..0392dc5426 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1228,6 +1228,7 @@ private PersistentPropertyPath getPath(String pathExpre return propertyPath; } + @Nullable private PersistentPropertyPath tryToResolvePersistentPropertyPath(PropertyPath path) { try { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index e2a65d5322..770f8ebe20 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -28,7 +28,6 @@ import java.util.Map; import java.util.Optional; -import lombok.Data; import org.bson.conversions.Bson; import org.bson.types.Code; import org.bson.types.ObjectId; @@ -49,12 +48,10 @@ import org.springframework.data.mongodb.core.geo.GeoJsonPolygon; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.FieldType; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; -import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.mapping.Unwrapped; import org.springframework.data.mongodb.core.query.BasicQuery; @@ -75,7 +72,6 @@ * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MockitoExtension.class) public class QueryMapperUnitTests { private QueryMapper mapper; @@ -1447,18 +1443,18 @@ static class ClassWithGeoTypes { @Field("geoJsonPointWithNameViaFieldAnnotation") GeoJsonPoint namedGeoJsonPoint; } - static class SimpeEntityWithoutId { + static class SimpleEntityWithoutId { String stringProperty; Integer integerProperty; } static class EntityWithComplexValueTypeMap { - Map map; + Map map; } static class EntityWithComplexValueTypeList { - List list; + List list; } static class WithExplicitTargetTypes { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java index 0f90bd2b9c..2d2dedc2ee 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java @@ -119,6 +119,9 @@ MongoMappingContext mappingContext() { mappingContext = new MongoMappingContext(); mappingContext.setInitialEntitySet(mappingContextConfigurer.initialEntitySet()); mappingContext.setAutoIndexCreation(mappingContextConfigurer.autocreateIndex); + if(mongoConverterConfigurer.customConversions != null) { + mappingContext.setSimpleTypeHolder(mongoConverterConfigurer.customConversions.getSimpleTypeHolder()); + } mappingContext.afterPropertiesSet(); } From 7dfe4604336ab79a1ee7cde721254be6a5e41906 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 21 Jun 2021 12:24:02 +0200 Subject: [PATCH 0442/1381] Fix field projection value conversion. The field projection conversion should actually only map field names and avoid value conversion. In the MongoId case an inclusion parameter (1) was unintentionally converted into its String representation which causes trouble on Mongo 4.4 servers. Fixes: #3668 Original pull request: #3678. --- .../mongodb/core/convert/QueryMapper.java | 37 +++++++++++-------- .../core/convert/QueryMapperUnitTests.java | 14 +++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 0392dc5426..08f6458e95 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -195,19 +195,7 @@ public Document getMappedSort(Document sortObject, @Nullable MongoPersistentEnti return new Document(); } - sortObject = filterUnwrappedObjects(sortObject, entity); - - Document mappedSort = new Document(); - for (Map.Entry entry : BsonUtils.asMap(sortObject).entrySet()) { - - Field field = createPropertyField(entity, entry.getKey(), mappingContext); - if (field.getProperty() != null && field.getProperty().isUnwrapped()) { - continue; - } - - mappedSort.put(field.getMappedKey(), entry.getValue()); - } - + Document mappedSort = mapFieldsToPropertyNames(sortObject, entity); mapMetaAttributes(mappedSort, entity, MetaMapping.WHEN_PRESENT); return mappedSort; } @@ -225,13 +213,30 @@ public Document getMappedFields(Document fieldsObject, @Nullable MongoPersistent Assert.notNull(fieldsObject, "FieldsObject must not be null!"); - fieldsObject = filterUnwrappedObjects(fieldsObject, entity); - - Document mappedFields = getMappedObject(fieldsObject, entity); + Document mappedFields = mapFieldsToPropertyNames(fieldsObject, entity); mapMetaAttributes(mappedFields, entity, MetaMapping.FORCE); return mappedFields; } + private Document mapFieldsToPropertyNames(Document fields, @Nullable MongoPersistentEntity entity) { + + if (fields.isEmpty()) { + return new Document(); + + } + Document target = new Document(); + for (Map.Entry entry : BsonUtils.asMap(filterUnwrappedObjects(fields, entity)).entrySet()) { + + Field field = createPropertyField(entity, entry.getKey(), mappingContext); + if (field.getProperty() != null && field.getProperty().isUnwrapped()) { + continue; + } + + target.put(field.getMappedKey(), entry.getValue()); + } + return target; + } + private void mapMetaAttributes(Document source, @Nullable MongoPersistentEntity entity, MetaMapping metaMapping) { if (entity == null) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 770f8ebe20..ba883d14c4 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -50,6 +50,7 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; 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.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.TextScore; @@ -1304,6 +1305,13 @@ void allowsUsingFieldPathsForPropertiesHavingCustomConversionRegistered() { assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class))).isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive")); } + @Test // GH-3668 + void mapStringIdFieldProjection() { + + org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1), context.getPersistentEntity(WithStringId.class)); + assertThat(mappedFields).containsEntry("_id", 1); + } + class WithDeepArrayNesting { List level0; @@ -1367,6 +1375,12 @@ class Sample { @Id private String foo; } + class WithStringId { + + @MongoId String id; + String name; + } + class BigIntegerId { @Id private BigInteger id; From 9dda0a2f9374b5f6f7d72f9a06a06cfd4f7204e1 Mon Sep 17 00:00:00 2001 From: larsw Date: Mon, 21 Jun 2021 13:58:07 +0200 Subject: [PATCH 0443/1381] Add closing quote to GeoJson javadoc. Closes #3677 --- .../java/org/springframework/data/mongodb/core/geo/GeoJson.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java index 3c659f7cc1..b033d2b6d5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.core.geo; /** - * Interface definition for structures defined in GeoJSON format. * * @author Christoph Strobl * @since 1.7 From 826015e9c1e749c51d23dddfff8bd4b5187145bf Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Jun 2021 14:36:49 +0200 Subject: [PATCH 0444/1381] Update reference docs to use correct MongoClient. Closes #3666 --- src/main/asciidoc/reference/mongodb.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 7e0ef51328..fb35bb655b 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -214,7 +214,7 @@ public class AppConfig { ---- ==== -To access the `com.mongodb.client.MongoClient` object created by the `MongoClientFactoryBean` in other `@Configuration` classes or your own classes, use a `private @Autowired Mongo mongo;` field. +To access the `com.mongodb.client.MongoClient` object created by the `MongoClientFactoryBean` in other `@Configuration` classes or your own classes, use a `private @Autowired MongoClient mongoClient;` field. [[mongo.mongo-xml-config]] === Registering a Mongo Instance by Using XML-based Metadata From 2a5ae0da37262762965c176cf9b7016606730ce4 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Jun 2021 15:17:49 +0200 Subject: [PATCH 0445/1381] Updated changelog. See #3649 --- src/main/resources/changelog.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 3de91d4a95..e611a3a5f8 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,15 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.10 (2021-06-22) +-------------------------------------- +* #3677 - Add missing double quote to GeoJson.java JSDoc header. +* #3666 - Documentation references outdated `Mongo` client. +* #3659 - [3.2.1] Indexing Class with Custom Converter -> Couldn't find PersistentEntity for property private [...]. +* #3635 - $floor isOrOrNor() return true. +* #3633 - NPE in QueryMapper when use Query with `null` as value. + + Changes in version 3.2.1 (2021-05-14) ------------------------------------- * #3638 - Introduce template method for easier customization of fragments. @@ -3442,5 +3451,6 @@ Repository + From c70c29b2c7443296a6cb80db7c29cbdc188a46c6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Jun 2021 15:51:33 +0200 Subject: [PATCH 0446/1381] Updated changelog. See #3650 --- src/main/resources/changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index e611a3a5f8..18ac26a430 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,17 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.2.2 (2021-06-22) +------------------------------------- +* #3677 - Add missing double quote to GeoJson.java JSDoc header. +* #3668 - Projection on the _id field returns wrong result when using `@MongoId` (MongoDB 4.4). +* #3666 - Documentation references outdated `Mongo` client. +* #3660 - MappingMongoConverter problem: ConversionContext#convert does not try to use custom converters first. +* #3659 - [3.2.1] Indexing Class with Custom Converter -> Couldn't find PersistentEntity for property private [...]. +* #3635 - $floor isOrOrNor() return true. +* #3633 - NPE in QueryMapper when use Query with `null` as value. + + Changes in version 3.1.10 (2021-06-22) -------------------------------------- * #3677 - Add missing double quote to GeoJson.java JSDoc header. @@ -3452,5 +3463,6 @@ Repository + From 85a30ec91597a451c4c1c04b41a1e36995e1a727 Mon Sep 17 00:00:00 2001 From: Gatto Date: Wed, 23 Jun 2021 21:07:29 -0300 Subject: [PATCH 0447/1381] Add equals and hashCode to UnwrappedMongoPersistentProperty. Fixes #3683 Original Pull Request: #3684 --- .../core/mapping/UnwrapEntityContext.java | 33 +++++++++++++++++++ .../UnwrappedMongoPersistentProperty.java | 31 +++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java index f4f54e9578..81e2926058 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java @@ -15,8 +15,11 @@ */ package org.springframework.data.mongodb.core.mapping; +import java.util.Objects; + /** * @author Christoph Strobl + * @author Rogério Meneguelli Gatto * @since 3.2 */ class UnwrapEntityContext { @@ -30,4 +33,34 @@ public UnwrapEntityContext(MongoPersistentProperty property) { public MongoPersistentProperty getProperty() { return property; } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(property); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + UnwrapEntityContext other = (UnwrapEntityContext) obj; + + return Objects.equals(property, other.property); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java index 6d4b163d22..0570a582b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java @@ -18,6 +18,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.Objects; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentEntity; @@ -29,6 +30,7 @@ * Unwrapped variant of {@link MongoPersistentProperty}. * * @author Christoph Strobl + * @author Rogério Meneguelli Gatto * @since 3.2 * @see Unwrapped */ @@ -321,4 +323,33 @@ public PersistentPropertyAccessor getAccessorForOwner(T owner) { return delegate.getAccessorForOwner(owner); } + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(delegate, context); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + UnwrappedMongoPersistentProperty other = (UnwrappedMongoPersistentProperty) obj; + + return Objects.equals(delegate, other.delegate) && Objects.equals(context, other.context); + } } From 82d67c1dbbab41c2b58ffa624a1a6925ba1b1091 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 24 Jun 2021 13:22:38 +0200 Subject: [PATCH 0448/1381] Favor ObjectUtils over Objects for equals/hashCode. Original Pull Request: #3684 --- .../core/mapping/UnwrapEntityContext.java | 26 +++++++-------- .../UnwrappedMongoPersistentProperty.java | 32 +++++++++++-------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java index 81e2926058..5240aef5c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrapEntityContext.java @@ -15,7 +15,7 @@ */ package org.springframework.data.mongodb.core.mapping; -import java.util.Objects; +import org.springframework.util.ObjectUtils; /** * @author Christoph Strobl @@ -36,21 +36,11 @@ public MongoPersistentProperty getProperty() { /* * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return Objects.hash(property); - } - - /* - * (non-Javadoc) - * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { + if (this == obj) { return true; } @@ -59,8 +49,16 @@ public boolean equals(Object obj) { return false; } - UnwrapEntityContext other = (UnwrapEntityContext) obj; + UnwrapEntityContext that = (UnwrapEntityContext) obj; + return ObjectUtils.nullSafeEquals(property, that.property); + } - return Objects.equals(property, other.property); + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(property); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java index 0570a582b1..8f24bab61b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java @@ -18,13 +18,13 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Objects; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; /** * Unwrapped variant of {@link MongoPersistentProperty}. @@ -325,21 +325,11 @@ public PersistentPropertyAccessor getAccessorForOwner(T owner) { /* * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return Objects.hash(delegate, context); - } - - /* - * (non-Javadoc) - * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { + if (this == obj) { return true; } @@ -348,8 +338,22 @@ public boolean equals(Object obj) { return false; } - UnwrappedMongoPersistentProperty other = (UnwrappedMongoPersistentProperty) obj; + UnwrappedMongoPersistentProperty that = (UnwrappedMongoPersistentProperty) obj; + if (!ObjectUtils.nullSafeEquals(delegate, that.delegate)) { + return false; + } + return ObjectUtils.nullSafeEquals(context, that.context); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { - return Objects.equals(delegate, other.delegate) && Objects.equals(context, other.context); + int result = ObjectUtils.nullSafeHashCode(delegate); + result = 31 * result + ObjectUtils.nullSafeHashCode(context); + return result; } } From 61d3a0bd1f8e51490dc40e7ff679a4e5b605c7b7 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 1 Jul 2021 08:50:24 +0200 Subject: [PATCH 0449/1381] Fix NPE when reading/mapping null value inside collection. Closes: #3686 --- .../core/convert/MappingMongoConverter.java | 3 +- .../core/convert/ReferenceLookupDelegate.java | 3 +- .../MappingMongoConverterUnitTests.java | 39 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) 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 732e8c9a51..aced009cda 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 @@ -1269,7 +1269,7 @@ protected Object readCollectionOrArray(ConversionContext context, Collection } for (Object element : source) { - items.add(context.convert(element, componentType)); + items.add(element != null ? context.convert(element, componentType) : element); } return getPotentiallyConvertedSimpleRead(items, targetType.getType()); @@ -2013,6 +2013,7 @@ protected static class ConversionContext { @SuppressWarnings("unchecked") public S convert(Object source, TypeInformation typeHint) { + Assert.notNull(source, "Source must not be null"); Assert.notNull(typeHint, "TypeInformation must not be null"); if (conversions.hasCustomReadTarget(source.getClass(), typeHint.getType())) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index 616abb325e..3ca730452f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -110,7 +110,8 @@ public Object readReference(MongoPersistentProperty property, Object value, Look return null; } - return entityReader.read(result.iterator().next(), property.getTypeInformation()); + Object resultValue = result.iterator().next(); + return resultValue != null ? entityReader.read(resultValue, property.getTypeInformation()) : null; } private ReferenceCollection computeReferenceContext(MongoPersistentProperty property, Object value, diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 0361571414..c8e2fec155 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -2532,6 +2532,41 @@ void shouldWriteNullPropertyCorrectly() { assertThat(document).containsEntry("writeAlwaysPerson", null).doesNotContainKey("writeNonNullPerson"); } + @Test // GH-3686 + void readsCollectionContainingNullValue() { + + org.bson.Document source = new org.bson.Document("items", Arrays.asList(new org.bson.Document("itemKey", "i1"), null, new org.bson.Document("itemKey", "i3"))); + + Order target = converter.read(Order.class, source); + + assertThat(target.items) + .map(it -> it != null ? it.itemKey : null) + .containsExactly("i1", null, "i3"); + } + + @Test // GH-3686 + void readsArrayContainingNullValue() { + + org.bson.Document source = new org.bson.Document("arrayOfStrings", Arrays.asList("i1", null, "i3")); + + WithArrays target = converter.read(WithArrays.class, source); + + assertThat(target.arrayOfStrings).containsExactly("i1", null, "i3"); + } + + @Test // GH-3686 + void readsMapContainingNullValue() { + + org.bson.Document source = new org.bson.Document("mapOfObjects", new org.bson.Document("item1", "i1").append("item2", null).append("item3", "i3")); + + ClassWithMapProperty target = converter.read(ClassWithMapProperty.class, source); + + assertThat(target.mapOfObjects) + .containsEntry("item1", "i1") + .containsEntry("item2", null) + .containsEntry("item3", "i3"); + } + static class GenericType { T content; } @@ -2893,6 +2928,10 @@ static class WithArrayInConstructor { } + static class WithArrays { + String[] arrayOfStrings; + } + // DATAMONGO-1898 // DATACMNS-1278 From 5cffb3c07c3fa015479d032dbe7d6aec80a31808 Mon Sep 17 00:00:00 2001 From: David Julia Date: Sun, 27 Jun 2021 23:08:43 +1000 Subject: [PATCH 0450/1381] Fix Regression in generating queries with nested maps with numeric keys. While maps that have numeric keys work if there is only one map with an integer key, when there are multiple maps with numeric keys in a given query, it fails. Take the following example for a map called outer with numeric keys holding reference to another object with a map called inner with numeric keys: Updates that are meant to generate {"$set": {"outerMap.1234.inner.5678": "hello"}} are instead generating {"$set": {"outerMap.1234.inner.inner": "hello"}}, repeating the later map property name instead of using the integer key value. This commit adds unit tests both for the UpdateMapper and QueryMapper, which check multiple consecutive maps with numeric keys, and adds a fix in the KeyMapper. Because we cannot easily change the path parsing to somehow parse path parts corresponding to map keys differently, we address the issue in the KeyMapper. We keep track of the partial path corresponding to the current property and use it to skip adding the duplicated property name for the map to the query, and instead add the key. This is a bit redundant in that we now have both an iterator and an index-based way of accessing the path parts, but it gets the tests passing and fixes the issue without making a large change to the current approach. Fixes: #3688 Original Pull Request: #3689 --- .../mongodb/core/convert/QueryMapper.java | 22 ++++++++++++--- .../core/convert/QueryMapperUnitTests.java | 27 +++++++++++++++++++ .../core/convert/UpdateMapperUnitTests.java | 15 +++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 08f6458e95..e1682fa6e9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -69,6 +69,7 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author David Julia */ public class QueryMapper { @@ -1367,11 +1368,17 @@ public TypeInformation getTypeHint() { static class KeyMapper { private final Iterator iterator; + private int currentIndex; + private String currentPropertyRoot; + private final List pathParts; public KeyMapper(String key, MappingContext, MongoPersistentProperty> mappingContext) { - this.iterator = Arrays.asList(key.split("\\.")).iterator(); + this.pathParts = Arrays.asList(key.split("\\.")); + this.currentPropertyRoot = pathParts.get(0); + this.currentIndex = 0; + this.iterator = pathParts.iterator(); this.iterator.next(); } @@ -1389,16 +1396,25 @@ protected String mapPropertyName(MongoPersistentProperty property) { while (inspect) { String partial = iterator.next(); + currentIndex++; - boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike(); + boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike() ; + if(property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()){ + partial = iterator.next(); + currentIndex++; + } - if (isPositional || property.isMap()) { + if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) { mappedName.append(".").append(partial); } inspect = isPositional && iterator.hasNext(); } + if(currentIndex + 1 < pathParts.size()) { + currentIndex++; + currentPropertyRoot = pathParts.get(currentIndex); + } return mappedName.toString(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index ba883d14c4..efd354b866 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -72,6 +72,7 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author David Julia */ public class QueryMapperUnitTests { @@ -730,6 +731,28 @@ void mappingShouldRetainNumericMapKey() { assertThat(document).containsKey("map.1.stringProperty"); } + @Test // GH-3688 + void mappingShouldRetainNestedNumericMapKeys() { + + Query query = query(where("outerMap.1.map.2.stringProperty").is("ba'alzamon")); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class)); + + assertThat(document).containsKey("outerMap.1.map.2.stringProperty"); + } + + @Test // GH-3688 + void mappingShouldAllowSettingEntireNestedNumericKeyedMapValue() { + + Query query = query(where("outerMap.1.map").is(null)); //newEntityWithComplexValueTypeMap() + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class)); + + assertThat(document).containsKey("outerMap.1.map"); + } + @Test // DATAMONGO-1269 void mappingShouldRetainNumericPositionInList() { @@ -1467,6 +1490,10 @@ static class EntityWithComplexValueTypeMap { Map map; } + static class EntityWithIntKeyedMapOfMap{ + Map outerMap; + } + static class EntityWithComplexValueTypeList { List list; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index a8d5f12b9f..bba9811e56 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -67,6 +67,7 @@ * @author Thomas Darimont * @author Mark Paluch * @author Pavel Vodrazka + * @author David Julia */ @ExtendWith(MockitoExtension.class) class UpdateMapperUnitTests { @@ -1179,6 +1180,16 @@ void numericKeyInMapOfNestedPath() { assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"map.601218778970110001827396.value\": \"testing\"}}"); } + @Test // GH-3688 + void multipleNumericKeysInNestedPath() { + + Update update = new Update().set("intKeyedMap.12345.map.0", "testing"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithIntKeyedMap.class)); + + assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"intKeyedMap.12345.map.0\": \"testing\"}}"); + } + @Test // GH-3566 void mapsObjectClassPropertyFieldInMapValueTypeAsKey() { @@ -1425,6 +1436,10 @@ static class EntityWithObjectMap { Map concreteMap; } + static class EntityWithIntKeyedMap{ + Map intKeyedMap; + } + static class ClassWithEnum { Allocation allocation; From ef29e69a87022db0ca0e475dc4b276dccab0597d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 5 Jul 2021 10:28:39 +0200 Subject: [PATCH 0451/1381] Polishing. Simplify KeyMapper current property/index setup. Original Pull Request: #3689 --- .../data/mongodb/core/convert/QueryMapper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index e1682fa6e9..7a14f07c4c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1376,10 +1376,9 @@ public KeyMapper(String key, MappingContext, MongoPersistentProperty> mappingContext) { this.pathParts = Arrays.asList(key.split("\\.")); - this.currentPropertyRoot = pathParts.get(0); - this.currentIndex = 0; this.iterator = pathParts.iterator(); - this.iterator.next(); + this.currentPropertyRoot = iterator.next(); + this.currentIndex = 0; } /** @@ -1391,6 +1390,7 @@ public KeyMapper(String key, protected String mapPropertyName(MongoPersistentProperty property) { StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property)); + boolean inspect = iterator.hasNext(); while (inspect) { From 4f65bb0810cceeaf1fbf783aecd13c3ebff20aab Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 22 Jun 2021 14:03:52 +0200 Subject: [PATCH 0452/1381] Fix mapping context setup to include simple type holder. Original pull request: #3687. Resolves #3656 --- .../data/mongodb/core/MongoTemplateUnitTests.java | 1 + .../data/mongodb/core/ReactiveMongoTemplateUnitTests.java | 2 ++ .../core/convert/DbRefMappingMongoConverterUnitTests.java | 1 + .../data/mongodb/core/convert/MappingMongoConverterTests.java | 2 ++ .../mongodb/core/convert/MappingMongoConverterUnitTests.java | 1 + .../data/mongodb/core/query/BasicQueryUnitTests.java | 4 ++++ .../mongodb/test/util/MongoTestTemplateConfiguration.java | 2 ++ 7 files changed, 13 insertions(+) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index c3ee9b32ff..68c83a2757 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -206,6 +206,7 @@ void beforeEach() { this.mappingContext = new MongoMappingContext(); mappingContext.setAutoIndexCreation(true); + mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); mappingContext.afterPropertiesSet(); this.converter = spy(new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 931ea75cea..5c5a307f1d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -23,6 +23,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -189,6 +190,7 @@ void beforeEach() { when(aggregatePublisher.first()).thenReturn(findPublisher); this.mappingContext = new MongoMappingContext(); + this.mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); this.template = new ReactiveMongoTemplate(factory, converter); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index d5285e7d2e..b677d90df5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -85,6 +85,7 @@ void setUp() { this.dbRefResolver = spy(new DefaultDbRefResolver(dbFactory)); this.mappingContext = new MongoMappingContext(); + this.mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); this.converter = new MappingMongoConverter(dbRefResolver, mappingContext); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index 2b17ed4b06..c9a4937125 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -31,6 +31,7 @@ import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -80,6 +81,7 @@ void setUp() { dbRefResolver = spy(new DefaultDbRefResolver(factory)); mappingContext = new MongoMappingContext(); + mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); mappingContext.setInitialEntitySet(new HashSet<>( Arrays.asList(WithLazyDBRefAsConstructorArg.class, WithLazyDBRef.class, WithJavaTimeTypes.class))); mappingContext.setAutoIndexCreation(false); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index c8e2fec155..369f6dbdef 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -1702,6 +1702,7 @@ void convertsJava8DateTimeTypesToDateAndBack() { } @Test // DATAMONGO-1128 + @Disabled("really we should find a solution for this") void writesOptionalsCorrectly() { TypeWithOptional type = new TypeWithOptional(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java index 1a7477f099..d9ef1cce30 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/BasicQueryUnitTests.java @@ -24,6 +24,9 @@ import org.bson.Document; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledForJreRange; +import org.junit.jupiter.api.condition.DisabledOnJre; +import org.junit.jupiter.api.condition.JRE; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -64,6 +67,7 @@ public void overridesSortCorrectly() { } @Test // DATAMONGO-1093 + @DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "EqualsVerifier uses reflection on Optional") public void equalsContract() { BasicQuery query1 = new BasicQuery("{ \"name\" : \"Thomas\"}", "{\"name\":1, \"age\":1}"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java index 2d2dedc2ee..ee75da8b19 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java @@ -121,6 +121,8 @@ MongoMappingContext mappingContext() { mappingContext.setAutoIndexCreation(mappingContextConfigurer.autocreateIndex); if(mongoConverterConfigurer.customConversions != null) { mappingContext.setSimpleTypeHolder(mongoConverterConfigurer.customConversions.getSimpleTypeHolder()); + } else { + mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); } mappingContext.afterPropertiesSet(); } From 403f0019d55dd5b70d7132549f82acb8ae16d6bb Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 23 Jun 2021 15:45:14 +0200 Subject: [PATCH 0453/1381] Fix Optional handling in query creation and result processing. Original pull request: #3687. Resolves #3656 --- .../core/mapping/MongoMappingContext.java | 6 ++++ .../mapping/MongoMappingContextUnitTests.java | 31 +++++++++++++++++++ ...tractPersonRepositoryIntegrationTests.java | 13 ++++++++ .../mongodb/repository/PersonRepository.java | 2 ++ .../repository/PersonSummaryWithOptional.java | 24 ++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index c204434809..38381fb994 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -26,6 +26,7 @@ import org.springframework.data.mapping.model.Property; import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.NullableWrapperConverters; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; @@ -69,6 +70,11 @@ public void setFieldNamingStrategy(@Nullable FieldNamingStrategy fieldNamingStra */ @Override protected boolean shouldCreatePersistentEntityFor(TypeInformation type) { + + if(NullableWrapperConverters.supports(type.getType())) { + return false; + } + return !MongoSimpleTypes.HOLDER.isSimpleType(type.getType()) && !AbstractMap.class.isAssignableFrom(type.getType()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java index a7e454c52a..f0cc1a2f32 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.Locale; import java.util.Map; +import java.util.Optional; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -35,6 +36,7 @@ import org.springframework.data.mapping.model.FieldNamingStrategy; import com.mongodb.DBRef; +import org.springframework.data.util.TypeInformation; /** * Unit tests for {@link MongoMappingContext}. @@ -173,6 +175,26 @@ void shouldNotCreateEntityForEnum() { assertThat(context.getPersistentEntity(ChronoUnit.class)).isNull(); } + @Test // GH-3656 + void shouldNotCreateEntityForOptionalGetter() { + + MongoMappingContext context = new MongoMappingContext(); + MongoPersistentEntity entity = context.getRequiredPersistentEntity(InterfaceWithMethodReturningOptional.class); + + assertThat(context.getPersistentEntities()).map(it -> it.getType()).doesNotContain((Class) + Optional.class).contains((Class)Person.class); + } + + @Test // GH-3656 + void shouldNotCreateEntityForOptionalField() { + + MongoMappingContext context = new MongoMappingContext(); + MongoPersistentEntity entity = context.getRequiredPersistentEntity(ClassWithOptionalField.class); + + assertThat(context.getPersistentEntities()).map(it -> it.getType()).doesNotContain((Class) + Optional.class).contains((Class)Person.class); + } + public class SampleClass { Map children; @@ -244,4 +266,13 @@ class ClassWithChronoUnit { ChronoUnit unit; } + + interface InterfaceWithMethodReturningOptional { + + Optional getPerson(); + } + + class ClassWithOptionalField { + Optional person; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index d576913850..e462458ae8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -1460,4 +1460,17 @@ void executesQueryWithDocumentReferenceCorrectly() { List result = repository.findBySpiritAnimal(dave); assertThat(result).map(Person::getId).containsExactly(josh.getId()); } + + @Test //GH-3656 + void resultProjectionWithOptionalIsExcecutedCorrectly() { + + carter.setAddress(new Address("batman", "robin", "gotham")); + repository.save(carter); + + PersonSummaryWithOptional result = repository.findSummaryWithOptionalByLastname("Beauford"); + + assertThat(result).isNotNull(); + assertThat(result.getAddress()).isPresent(); + assertThat(result.getFirstname()).contains("Carter"); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 155cf7a7b9..9ac1282088 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -307,6 +307,8 @@ Page findByCustomQueryLastnameAndAddressStreetInList(String lastname, Li // DATAMONGO-1030 PersonSummaryDto findSummaryByLastname(String lastname); + PersonSummaryWithOptional findSummaryWithOptionalByLastname(String lastname); + @Query("{ ?0 : ?1 }") List findByKeyValue(String key, String value); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java new file mode 100644 index 0000000000..d6a98752bb --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonSummaryWithOptional.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 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 + * + * https://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.repository; + +import java.util.Optional; + +public interface PersonSummaryWithOptional { + + Optional

      getAddress(); + Optional getFirstname(); +} From 81bc3c599b1dc0bcc03bf409c92eb7a6fb814e7d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 25 Jun 2021 13:40:55 +0200 Subject: [PATCH 0454/1381] Disable tests on Java 16 that require class-based proxies. Original pull request: #3687. Resolves #3656 --- .../core/mapping/MongoMappingContext.java | 4 ++-- .../DbRefMappingMongoConverterUnitTests.java | 6 ++++++ ...RepositoryLazyLoadingIntegrationTests.java | 20 +++++++++---------- .../reference/document-references.adoc | 6 ++++++ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index 38381fb994..121658b065 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -71,7 +71,7 @@ public void setFieldNamingStrategy(@Nullable FieldNamingStrategy fieldNamingStra @Override protected boolean shouldCreatePersistentEntityFor(TypeInformation type) { - if(NullableWrapperConverters.supports(type.getType())) { + if (NullableWrapperConverters.supports(type.getType())) { return false; } @@ -139,7 +139,7 @@ public MongoPersistentEntity getPersistentEntity(MongoPersistentProperty pers MongoPersistentEntity entity = super.getPersistentEntity(persistentProperty); - if(entity == null || !persistentProperty.isUnwrapped()) { + if (entity == null || !persistentProperty.isUnwrapped()) { return entity; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index b677d90df5..56ab37a0f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -36,6 +36,8 @@ import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledForJreRange; +import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; @@ -181,6 +183,7 @@ void lazyLoadingProxyForLazyDbRefOnInterface() { } @Test // DATAMONGO-348 + @DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg. ArrayList require to open java.util.") void lazyLoadingProxyForLazyDbRefOnConcreteCollection() { String id = "42"; @@ -508,6 +511,7 @@ void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() { } @Test // DATAMONGO-1076 + @DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg. ArrayList require to open java.util.") void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoked() throws Exception { MongoPersistentEntity entity = mappingContext @@ -526,6 +530,7 @@ void shouldNotTriggerResolvingOfLazyLoadedProxyWhenFinalizeMethodIsInvoked() thr } @Test // DATAMONGO-1194 + @DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg. ArrayList require to open java.util.") void shouldBulkFetchListOfReferences() { String id1 = "1"; @@ -576,6 +581,7 @@ void shouldBulkFetchSetOfReferencesForConstructorCreation() { } @Test // DATAMONGO-1194 + @DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg. ArrayList require to open java.util.") void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointToDifferentCollections() { String id1 = "1"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java index 5cc8e82599..4ca82abf57 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java @@ -22,14 +22,15 @@ import java.util.Arrays; import java.util.List; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledForJreRange; +import org.junit.jupiter.api.condition.JRE; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; /** * Integration test for {@link PersonRepository} for lazy loading support. @@ -38,13 +39,13 @@ * @author Oliver Gierke */ @ContextConfiguration(locations = "PersonRepositoryIntegrationTests-context.xml") -@RunWith(SpringRunner.class) +@ExtendWith(SpringExtension.class) public class PersonRepositoryLazyLoadingIntegrationTests { @Autowired PersonRepository repository; @Autowired MongoOperations operations; - @Before + @BeforeEach public void setUp() throws InterruptedException { repository.deleteAll(); @@ -61,7 +62,6 @@ public void shouldLoadAssociationWithDbRefOnInterfaceAndLazyLoadingEnabled() thr Person person = new Person(); person.setFirstname("Oliver"); person.setFans(Arrays.asList(thomas)); - person.setRealFans(new ArrayList(Arrays.asList(thomas))); repository.save(person); Person oliver = repository.findById(person.id).get(); @@ -75,7 +75,8 @@ public void shouldLoadAssociationWithDbRefOnInterfaceAndLazyLoadingEnabled() thr } @Test // DATAMONGO-348 - public void shouldLoadAssociationWithDbRefOnConcreteCollectionAndLazyLoadingEnabled() throws Exception { + @DisabledForJreRange(min = JRE.JAVA_16, disabledReason = "Class Proxies for eg. ArrayList require to open java.util.") + public void shouldLoadAssociationWithDbRefOnConcreteCollectionAndLazyLoadingEnabled() { User thomas = new User(); thomas.username = "Thomas"; @@ -83,7 +84,6 @@ public void shouldLoadAssociationWithDbRefOnConcreteCollectionAndLazyLoadingEnab Person person = new Person(); person.setFirstname("Oliver"); - person.setFans(Arrays.asList(thomas)); person.setRealFans(new ArrayList(Arrays.asList(thomas))); repository.save(person); diff --git a/src/main/asciidoc/reference/document-references.adoc b/src/main/asciidoc/reference/document-references.adoc index 92badd2fa1..885d2d6ade 100644 --- a/src/main/asciidoc/reference/document-references.adoc +++ b/src/main/asciidoc/reference/document-references.adoc @@ -49,6 +49,9 @@ TIP: Lazily loaded ``DBRef``s can be hard to debug. Make sure tooling does not accidentally trigger proxy resolution by e.g. calling `toString()` or some inline debug rendering invoking property getters. Please consider to enable _trace_ logging for `org.springframework.data.mongodb.core.convert.DefaultDbRefResolver` to gain insight on `DBRef` resolution. +CAUTION: Lazy loading may require class proxies, that in turn, might need access to jdk internals, that are not open, starting with Java 16+, due to https://openjdk.java.net/jeps/396[JEP 396: Strongly Encapsulate JDK Internals by Default]. +For those cases please consider falling back to an interface type (eg. switch from `ArrayList` to `List`) or provide the required `--add-opens` argument. + [[mapping-usage.document-references]] === Using Document References @@ -136,6 +139,9 @@ Result order of `Collection` like properties is restored based on the used looku | Resolves properties eagerly by default. |=== +CAUTION: Lazy loading may require class proxies, that in turn, might need access to jdk internals, that are not open, starting with Java 16+, due to https://openjdk.java.net/jeps/396[JEP 396: Strongly Encapsulate JDK Internals by Default]. +For those cases please consider falling back to an interface type (eg. switch from `ArrayList` to `List`) or provide the required `--add-opens` argument. + `@DocumentReference(lookup)` allows defining filter queries that can be different from the `_id` field and therefore offer a flexible way of defining references between entities as demonstrated in the sample below, where the `Publisher` of a book is referenced by its acronym instead of the internal `id`. ==== From 7d0b070d1f8110b9ff5d976e55e49c30794e95f9 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Fri, 9 Jul 2021 15:26:44 +0200 Subject: [PATCH 0455/1381] Adapt to API consolidation in Spring Data Commons' PersistentProperty. Closes: #3700 Original Pull Request: #3701 Related to: spring-projects/spring-data-commons#2408 --- .../core/mapping/UnwrappedMongoPersistentProperty.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java index 8f24bab61b..a2194c173f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java @@ -147,6 +147,11 @@ public Iterable> getPersistentEntityTypes() { return delegate.getPersistentEntityTypes(); } + @Override + public Iterable> getPersistentEntityTypeInformation() { + return delegate.getPersistentEntityTypeInformation(); + } + @Override @Nullable public Method getGetter() { @@ -318,6 +323,11 @@ public Class getAssociationTargetType() { return delegate.getAssociationTargetType(); } + @Override + public TypeInformation getAssociationTargetTypeInformation() { + return delegate.getAssociationTargetTypeInformation(); + } + @Override public PersistentPropertyAccessor getAccessorForOwner(T owner) { return delegate.getAccessorForOwner(owner); From a6a2f0bde902e31ff41070e24a20c1af03b60edb Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 12 Jul 2021 14:56:44 +0200 Subject: [PATCH 0456/1381] Upgrade to MongoDB 4.3.0-beta4 Drivers. Closes: #3693 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a6d5da9170..98de438544 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.6.0-SNAPSHOT - 4.2.3 + 4.3.0-beta4 ${mongo} 1.19 From 42ab7d2f6378488d8f23be6f056748c9eb406f19 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 13 Jul 2021 08:27:51 +0200 Subject: [PATCH 0457/1381] Adapt to changes in AssertJ 3.20. Closes #3705 --- .../mongodb/test/util/DocumentAssert.java | 49 +++++-------------- 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java index db33b29b82..6f519c71e2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/DocumentAssert.java @@ -134,12 +134,12 @@ public DocumentAssert containsKey(String key) { return containsKeys(key); } - /* + /* * (non-Javadoc) - * @see org.assertj.core.api.AbstractMapAssert#containsKeys(java.lang.Object[]) + * @see org.assertj.core.api.AbstractMapAssert#containsKeysForProxy(java.lang.Object[]) */ @Override - public final DocumentAssert containsKeys(String... keys) { + protected DocumentAssert containsKeysForProxy(String[] keys) { Set notFound = new LinkedHashSet<>(); @@ -166,12 +166,12 @@ public DocumentAssert doesNotContainKey(String key) { return doesNotContainKeys(key); } - /* + /* * (non-Javadoc) - * @see org.assertj.core.api.AbstractMapAssert#doesNotContainKeys(java.lang.Object[]) + * @see org.assertj.core.api.AbstractMapAssert#doesNotContainKeysForProxy(java.lang.Object[]) */ @Override - public final DocumentAssert doesNotContainKeys(String... keys) { + protected DocumentAssert doesNotContainKeysForProxy(String[] keys) { Set found = new LinkedHashSet<>(); for (String key : keys) { @@ -191,13 +191,8 @@ public final DocumentAssert doesNotContainKeys(String... keys) { // used in soft assertions which need to be able to proxy method - @SafeVarargs requiring method to be final prevents // using proxies. - /* - * (non-Javadoc) - * @see org.assertj.core.api.AbstractMapAssert#contains(java.util.Map.Entry[]) - */ - @SafeVarargs @Override - public final DocumentAssert contains(Map.Entry... entries) { + protected DocumentAssert containsForProxy(Entry[] entries) { // if both actual and values are empty, then assertion passes. if (actual.isEmpty() && entries.length == 0) { @@ -216,14 +211,8 @@ public final DocumentAssert contains(Map.Entry... entries) { - + protected DocumentAssert containsAnyOfForProxy(Entry[] entries) { for (Map.Entry entry : entries) { if (containsEntry(entry)) { return myself; @@ -233,24 +222,13 @@ public final DocumentAssert containsAnyOf(Map.Entry... entries) { + protected DocumentAssert containsOnlyForProxy(Entry[] entries) { throw new UnsupportedOperationException(); } - /* - * (non-Javadoc) - * @see org.assertj.core.api.AbstractMapAssert#doesNotContain(java.util.Map.Entry[]) - */ - @SafeVarargs @Override - public final DocumentAssert doesNotContain(Map.Entry... entries) { - + protected DocumentAssert doesNotContainForProxy(Entry[] entries) { Set> found = new LinkedHashSet<>(); for (Map.Entry entry : entries) { @@ -265,13 +243,8 @@ public final DocumentAssert doesNotContain(Map.Entry... entries) { + protected DocumentAssert containsExactlyForProxy(Entry[] entries) { throw new UnsupportedOperationException(); } From 93b9f23b077cd60c43b22aa66b7431c2500ccf6a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 13 Jul 2021 08:42:24 +0200 Subject: [PATCH 0458/1381] Polishing. Fix proxy comparison. See #3705 --- .../data/mongodb/core/convert/LazyLoadingProxyFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java index f77b96c71f..887ddfe78d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java @@ -167,7 +167,7 @@ public Object intercept(Object o, Method method, Object[] args, MethodProxy prox } if (ReflectionUtils.isEqualsMethod(method)) { - return proxyEquals(proxy, args[0]); + return proxyEquals(o, args[0]); } if (ReflectionUtils.isHashCodeMethod(method)) { From 5bd7ff141355e98843a0eca990a6018458dc6557 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 14 Jul 2021 07:44:00 +0200 Subject: [PATCH 0459/1381] Upgrade to MongoDB 4.3.0 Drivers. Closes: #3706 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 98de438544..b688f3ee50 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.6.0-SNAPSHOT - 4.3.0-beta4 + 4.3.0 ${mongo} 1.19 From 986ea39f902f65653c77ab32153c97ff8f7efb7e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 17 Jun 2021 10:50:13 +0200 Subject: [PATCH 0460/1381] Upgrade to Querydsl 5.0. Move off our own Querydsl copies, as Querydsl 5.0 ships MongoDB Document API support. Remove package-private duplicates of Querydsl code. Introduce SpringDataMongodbQuerySupport to provide a well-formatted toString representation of the actual query. Original Pull Request: #3674 --- .../support/MongodbDocumentSerializer.java | 459 ------------------ .../support/QuerydslAbstractMongodbQuery.java | 32 +- .../support/QuerydslAnyEmbeddedBuilder.java | 3 + .../QuerydslFetchableMongodbQuery.java | 272 ----------- .../support/QuerydslJoinBuilder.java | 67 --- .../repository/support/QuerydslMongoOps.java | 43 -- .../ReactiveSpringDataMongodbQuery.java | 79 ++- .../support/SpringDataMongodbQuery.java | 199 +++++++- .../SpringDataMongodbQuerySupport.java | 147 ++++++ .../support/SpringDataMongodbSerializer.java | 2 + .../SimpleReactiveMongoRepositoryTests.java | 3 +- 11 files changed, 383 insertions(+), 923 deletions(-) delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java delete mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java deleted file mode 100644 index 3f0d281cc4..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongodbDocumentSerializer.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright 2018-2021 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 - * - * https://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.repository.support; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.regex.Pattern; - -import org.bson.BsonJavaScript; -import org.bson.BsonRegularExpression; -import org.bson.Document; -import org.bson.types.ObjectId; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -import com.mongodb.DBRef; -import com.querydsl.core.types.*; -import com.querydsl.mongodb.MongodbOps; - -/** - *

      - * Serializes the given Querydsl query to a Document query for MongoDB. - *

      - *

      - * Original implementation source {@link com.querydsl.mongodb.MongodbSerializer} by {@literal The Querydsl Team} - * (http://www.querydsl.com/team) licensed under the Apache License, Version - * 2.0. - *

      - * Modified to use {@link Document} instead of {@link com.mongodb.DBObject}, updated nullable types and code format. Use - * Bson specific types and add {@link QuerydslMongoOps#NO_MATCH}. - * - * @author laimw - * @author Mark Paluch - * @author Christoph Strobl - * @author Mikhail Kaduchka - * @author Enrique Leon Molina - * @since 2.1 - */ -abstract class MongodbDocumentSerializer implements Visitor { - - @Nullable - Object handle(Expression expression) { - return expression.accept(this, null); - } - - /** - * Create the MongoDB specific query document. - * - * @param predicate must not be {@literal null}. - * @return empty {@link Document} by default. - */ - Document toQuery(Predicate predicate) { - - Object value = handle(predicate); - - if (value == null) { - return new Document(); - } - - Assert.isInstanceOf(Document.class, value, - () -> String.format("Invalid type. Expected Document but found %s", value.getClass())); - - return (Document) value; - } - - /** - * Create the MongoDB specific sort document. - * - * @param orderBys must not be {@literal null}. - * @return empty {@link Document} by default. - */ - Document toSort(List> orderBys) { - - Document sort = new Document(); - - orderBys.forEach(orderSpecifier -> { - - Object key = orderSpecifier.getTarget().accept(this, null); - - Assert.notNull(key, () -> String.format("Mapped sort key for %s must not be null!", orderSpecifier)); - sort.append(key.toString(), orderSpecifier.getOrder() == Order.ASC ? 1 : -1); - }); - - return sort; - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.types.Visitor#visit(com.querydsl.core.types.Constant, java.lang.Void) - */ - @Override - public Object visit(Constant expr, Void context) { - - if (!Enum.class.isAssignableFrom(expr.getType())) { - return expr.getConstant(); - } - - @SuppressWarnings("unchecked") // Guarded by previous check - Constant> expectedExpr = (Constant>) expr; - return expectedExpr.getConstant().name(); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.types.Visitor#visit(com.querydsl.core.types.TemplateExpression, java.lang.Void) - */ - @Override - public Object visit(TemplateExpression expr, Void context) { - throw new UnsupportedOperationException(); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.types.Visitor#visit(com.querydsl.core.types.FactoryExpression, java.lang.Void) - */ - @Override - public Object visit(FactoryExpression expr, Void context) { - throw new UnsupportedOperationException(); - } - - protected String asDBKey(Operation expr, int index) { - - String key = (String) asDBValue(expr, index); - - Assert.hasText(key, () -> String.format("Mapped key must not be null nor empty for expression %s.", expr)); - return key; - } - - @Nullable - protected Object asDBValue(Operation expr, int index) { - return expr.getArg(index).accept(this, null); - } - - private String regexValue(Operation expr, int index) { - - Object value = expr.getArg(index).accept(this, null); - - Assert.notNull(value, () -> String.format("Regex for %s must not be null.", expr)); - return Pattern.quote(value.toString()); - } - - protected Document asDocument(String key, @Nullable Object value) { - return new Document(key, value); - } - - @SuppressWarnings("unchecked") - @Override - public Object visit(Operation expr, Void context) { - - Operator op = expr.getOperator(); - if (op == Ops.EQ) { - - if (expr.getArg(0) instanceof Operation) { - Operation lhs = (Operation) expr.getArg(0); - if (lhs.getOperator() == Ops.COL_SIZE || lhs.getOperator() == Ops.ARRAY_SIZE) { - return asDocument(asDBKey(lhs, 0), asDocument("$size", asDBValue(expr, 1))); - } else { - throw new UnsupportedOperationException("Illegal operation " + expr); - } - } else if (expr.getArg(0) instanceof Path) { - Path path = (Path) expr.getArg(0); - Constant constant = (Constant) expr.getArg(1); - return asDocument(asDBKey(expr, 0), convert(path, constant)); - } - } else if (op == Ops.STRING_IS_EMPTY) { - return asDocument(asDBKey(expr, 0), ""); - } else if (op == Ops.AND) { - - Queue> pendingDocuments = collectConnectorArgs("$and", expr); - List> unmergeableDocuments = new ArrayList<>(); - List> generatedDocuments = new ArrayList<>(); - - while (!pendingDocuments.isEmpty()) { - - Map lhs = pendingDocuments.poll(); - - for (Map rhs : pendingDocuments) { - Set lhs2 = new LinkedHashSet<>(lhs.keySet()); - lhs2.retainAll(rhs.keySet()); - if (lhs2.isEmpty()) { - lhs.putAll(rhs); - } else { - unmergeableDocuments.add(rhs); - } - } - - generatedDocuments.add(lhs); - pendingDocuments = new LinkedList<>(unmergeableDocuments); - unmergeableDocuments = new LinkedList<>(); - } - - return generatedDocuments.size() == 1 ? generatedDocuments.get(0) : asDocument("$and", generatedDocuments); - } else if (op == Ops.NOT) { - // Handle the not's child - Operation subOperation = (Operation) expr.getArg(0); - Operator subOp = subOperation.getOperator(); - if (subOp == Ops.IN) { - return visit( - ExpressionUtils.operation(Boolean.class, Ops.NOT_IN, subOperation.getArg(0), subOperation.getArg(1)), - context); - } else { - Document arg = (Document) handle(expr.getArg(0)); - return negate(arg); - } - - } else if (op == Ops.OR) { - return asDocument("$or", collectConnectorArgs("$or", expr)); - } else if (op == Ops.NE) { - - Path path = (Path) expr.getArg(0); - Constant constant = (Constant) expr.getArg(1); - return asDocument(asDBKey(expr, 0), asDocument("$ne", convert(path, constant))); - - } else if (op == Ops.STARTS_WITH) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression("^" + regexValue(expr, 1))); - } else if (op == Ops.STARTS_WITH_IC) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression("^" + regexValue(expr, 1), "i")); - } else if (op == Ops.ENDS_WITH) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(regexValue(expr, 1) + "$")); - } else if (op == Ops.ENDS_WITH_IC) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(regexValue(expr, 1) + "$", "i")); - } else if (op == Ops.EQ_IGNORE_CASE) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression("^" + regexValue(expr, 1) + "$", "i")); - } else if (op == Ops.STRING_CONTAINS) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(".*" + regexValue(expr, 1) + ".*")); - } else if (op == Ops.STRING_CONTAINS_IC) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(".*" + regexValue(expr, 1) + ".*", "i")); - } else if (op == Ops.MATCHES) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(asDBValue(expr, 1).toString())); - } else if (op == Ops.MATCHES_IC) { - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(asDBValue(expr, 1).toString(), "i")); - } else if (op == Ops.LIKE) { - - String regex = ExpressionUtils.likeToRegex((Expression) expr.getArg(1)).toString(); - return asDocument(asDBKey(expr, 0), new BsonRegularExpression(regex)); - } else if (op == Ops.BETWEEN) { - - Document value = new Document("$gte", asDBValue(expr, 1)); - value.append("$lte", asDBValue(expr, 2)); - return asDocument(asDBKey(expr, 0), value); - } else if (op == Ops.IN) { - - int constIndex = 0; - int exprIndex = 1; - if (expr.getArg(1) instanceof Constant) { - constIndex = 1; - exprIndex = 0; - } - if (Collection.class.isAssignableFrom(expr.getArg(constIndex).getType())) { - @SuppressWarnings("unchecked") // guarded by previous check - Collection values = ((Constant>) expr.getArg(constIndex)).getConstant(); - return asDocument(asDBKey(expr, exprIndex), asDocument("$in", values)); - } else { - Path path = (Path) expr.getArg(exprIndex); - Constant constant = (Constant) expr.getArg(constIndex); - return asDocument(asDBKey(expr, exprIndex), convert(path, constant)); - } - } else if (op == Ops.NOT_IN) { - - int constIndex = 0; - int exprIndex = 1; - if (expr.getArg(1) instanceof Constant) { - - constIndex = 1; - exprIndex = 0; - } - if (Collection.class.isAssignableFrom(expr.getArg(constIndex).getType())) { - - @SuppressWarnings("unchecked") // guarded by previous check - Collection values = ((Constant>) expr.getArg(constIndex)).getConstant(); - return asDocument(asDBKey(expr, exprIndex), asDocument("$nin", values)); - } else { - - Path path = (Path) expr.getArg(exprIndex); - Constant constant = (Constant) expr.getArg(constIndex); - return asDocument(asDBKey(expr, exprIndex), asDocument("$ne", convert(path, constant))); - } - } else if (op == Ops.COL_IS_EMPTY) { - - List list = new ArrayList<>(2); - list.add(asDocument(asDBKey(expr, 0), new ArrayList())); - list.add(asDocument(asDBKey(expr, 0), asDocument("$exists", false))); - return asDocument("$or", list); - } else if (op == Ops.LT) { - return asDocument(asDBKey(expr, 0), asDocument("$lt", asDBValue(expr, 1))); - } else if (op == Ops.GT) { - return asDocument(asDBKey(expr, 0), asDocument("$gt", asDBValue(expr, 1))); - } else if (op == Ops.LOE) { - return asDocument(asDBKey(expr, 0), asDocument("$lte", asDBValue(expr, 1))); - } else if (op == Ops.GOE) { - return asDocument(asDBKey(expr, 0), asDocument("$gte", asDBValue(expr, 1))); - } else if (op == Ops.IS_NULL) { - return asDocument(asDBKey(expr, 0), asDocument("$exists", false)); - } else if (op == Ops.IS_NOT_NULL) { - return asDocument(asDBKey(expr, 0), asDocument("$exists", true)); - } else if (op == Ops.CONTAINS_KEY) { - - Path path = (Path) expr.getArg(0); - Expression key = expr.getArg(1); - return asDocument(visit(path, context) + "." + key.toString(), asDocument("$exists", true)); - } else if (op == MongodbOps.NEAR) { - return asDocument(asDBKey(expr, 0), asDocument("$near", asDBValue(expr, 1))); - } else if (op == MongodbOps.NEAR_SPHERE) { - return asDocument(asDBKey(expr, 0), asDocument("$nearSphere", asDBValue(expr, 1))); - } else if (op == MongodbOps.ELEM_MATCH) { - return asDocument(asDBKey(expr, 0), asDocument("$elemMatch", asDBValue(expr, 1))); - } else if (op == QuerydslMongoOps.NO_MATCH) { - return new Document("$where", new BsonJavaScript("function() { return false }")); - } - - throw new UnsupportedOperationException("Illegal operation " + expr); - } - - private Object negate(Document arg) { - - List list = new ArrayList<>(); - for (Map.Entry entry : arg.entrySet()) { - - if (entry.getKey().equals("$or")) { - list.add(asDocument("$nor", entry.getValue())); - } else if (entry.getKey().equals("$and")) { - - List list2 = new ArrayList<>(); - for (Object o : ((Collection) entry.getValue())) { - list2.add(negate((Document) o)); - } - list.add(asDocument("$or", list2)); - } else if (entry.getValue() instanceof Pattern || entry.getValue() instanceof BsonRegularExpression) { - list.add(asDocument(entry.getKey(), asDocument("$not", entry.getValue()))); - } else if (entry.getValue() instanceof Document) { - list.add(negate(entry.getKey(), (Document) entry.getValue())); - } else { - list.add(asDocument(entry.getKey(), asDocument("$ne", entry.getValue()))); - } - } - return list.size() == 1 ? list.get(0) : asDocument("$or", list); - } - - private Object negate(String key, Document value) { - - if (value.size() == 1) { - return asDocument(key, asDocument("$not", value)); - } else { - - List list2 = new ArrayList<>(); - for (Map.Entry entry2 : value.entrySet()) { - list2.add(asDocument(key, asDocument("$not", asDocument(entry2.getKey(), entry2.getValue())))); - } - - return asDocument("$or", list2); - } - } - - protected Object convert(Path property, Constant constant) { - - if (isReference(property)) { - return asReference(constant.getConstant()); - } else if (isId(property)) { - - if (isReference(property.getMetadata().getParent())) { - return asReferenceKey(property.getMetadata().getParent().getType(), constant.getConstant()); - } else if (constant.getType().equals(String.class) && isImplicitObjectIdConversion()) { - - String id = (String) constant.getConstant(); - return ObjectId.isValid(id) ? new ObjectId(id) : id; - } - } - return visit(constant, null); - } - - protected boolean isImplicitObjectIdConversion() { - return true; - } - - protected DBRef asReferenceKey(Class entity, Object id) { - // TODO override in subclass - throw new UnsupportedOperationException(); - } - - protected abstract DBRef asReference(Object constant); - - protected abstract boolean isReference(@Nullable Path arg); - - protected boolean isId(Path arg) { - // TODO override in subclass - return false; - } - - @Override - public String visit(Path expr, Void context) { - - PathMetadata metadata = expr.getMetadata(); - - if (metadata.getParent() != null) { - - Path parent = metadata.getParent(); - if (parent.getMetadata().getPathType() == PathType.DELEGATE) { - parent = parent.getMetadata().getParent(); - } - if (metadata.getPathType() == PathType.COLLECTION_ANY) { - return visit(parent, context); - } else if (parent.getMetadata().getPathType() != PathType.VARIABLE) { - - String rv = getKeyForPath(expr, metadata); - String parentStr = visit(parent, context); - return rv != null ? parentStr + "." + rv : parentStr; - } - } - return getKeyForPath(expr, metadata); - } - - protected String getKeyForPath(Path expr, PathMetadata metadata) { - return metadata.getElement().toString(); - } - - @Override - public Object visit(SubQueryExpression expr, Void context) { - throw new UnsupportedOperationException(); - } - - @Override - public Object visit(ParamExpression expr, Void context) { - throw new UnsupportedOperationException(); - } - - private LinkedList> collectConnectorArgs(String operator, Operation operation) { - - LinkedList> pendingDocuments = new LinkedList<>(); - for (Expression exp : operation.getArgs()) { - Map document = (Map) handle(exp); - if (document.keySet().size() == 1 && document.containsKey(operator)) { - pendingDocuments.addAll((Collection>) document.get(operator)); - } else { - pendingDocuments.add(document); - } - } - return pendingDocuments; - - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java index 422eea5778..b255d20273 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java @@ -34,6 +34,8 @@ import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.ParamExpression; import com.querydsl.core.types.Predicate; +import com.querydsl.mongodb.document.AbstractMongodbQuery; +import com.querydsl.mongodb.document.MongodbDocumentSerializer; /** * {@code QuerydslAbstractMongodbQuery} provides a base class for general Querydsl query implementation. @@ -49,8 +51,12 @@ * @author Mark Paluch * @author Christoph Strobl * @since 2.1 + * @deprecated since 3.3, use Querydsl's {@link AbstractMongodbQuery} directly. This class is deprecated for removal + * with the next major release. */ +@Deprecated public abstract class QuerydslAbstractMongodbQuery> + extends AbstractMongodbQuery implements SimpleQuery { private static final JsonWriterSettings JSON_WRITER_SETTINGS = JsonWriterSettings.builder().outputMode(JsonMode.SHELL) @@ -67,6 +73,8 @@ public abstract class QuerydslAbstractMongodbQuery((Q) this, new DefaultQueryMetadata(), false); this.serializer = serializer; } @@ -158,22 +166,6 @@ protected Document createProjection(@Nullable Expression projectionExpression return projection; } - /** - * Compute the filer {@link Document} from the given {@link Predicate}. - * - * @param predicate can be {@literal null}. - * @return an empty {@link Document} if predicate is {@literal null}. - * @see MongodbDocumentSerializer#toQuery(Predicate) - */ - protected Document createQuery(@Nullable Predicate predicate) { - - if (predicate == null) { - return new Document(); - } - - return serializer.toQuery(predicate); - } - /** * Compute the sort {@link Document} from the given list of {@link OrderSpecifier order specifiers}. * @@ -194,14 +186,6 @@ QueryMixin getQueryMixin() { return queryMixin; } - /** - * Get the where definition as a Document instance - * - * @return - */ - Document asDocument() { - return createQuery(queryMixin.getMetadata().getWhere()); - } /** * Returns the {@literal Mongo Shell} representation of the query.
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java index 3ba84a2dd3..b6935a5e8f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAnyEmbeddedBuilder.java @@ -37,7 +37,10 @@ * @author Mark Paluch * @author Christoph Strobl * @since 2.1 + * @deprecated since 3.3, use Querydsl's {@link com.querydsl.mongodb.document.AnyEmbeddedBuilder} directly. This class + * is deprecated for removal with the next major release. */ +@Deprecated public class QuerydslAnyEmbeddedBuilder, K> { private final QueryMixin queryMixin; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java deleted file mode 100644 index 36057d58c9..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslFetchableMongodbQuery.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2018-2021 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 - * - * https://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.repository.support; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithProjection; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.query.BasicQuery; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.lang.Nullable; -import org.springframework.util.LinkedMultiValueMap; - -import com.mysema.commons.lang.CloseableIterator; -import com.querydsl.core.Fetchable; -import com.querydsl.core.JoinExpression; -import com.querydsl.core.QueryMetadata; -import com.querydsl.core.QueryModifiers; -import com.querydsl.core.QueryResults; -import com.querydsl.core.types.Expression; -import com.querydsl.core.types.ExpressionUtils; -import com.querydsl.core.types.Operation; -import com.querydsl.core.types.OrderSpecifier; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.CollectionPathBase; - -/** - * {@link Fetchable} MongoDB query with utilizing {@link MongoOperations} for command execution. - * - * @param result type - * @param concrete subtype - * @author Mark Paluch - * @author Christoph Strobl - * @since 2.1 - */ -abstract class QuerydslFetchableMongodbQuery> - extends QuerydslAbstractMongodbQuery implements Fetchable { - - private final Class entityClass; - private final String collection; - private final MongoOperations mongoOperations; - private final FindWithProjection find; - - QuerydslFetchableMongodbQuery(MongodbDocumentSerializer serializer, Class entityClass, String collection, - MongoOperations mongoOperations) { - - super(serializer); - - this.entityClass = (Class) entityClass; - this.collection = collection; - this.mongoOperations = mongoOperations; - find = mongoOperations.query(this.entityClass).inCollection(collection); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.Fetchable#iterable() - */ - @Override - public CloseableIterator iterate() { - - org.springframework.data.util.CloseableIterator stream = mongoOperations.stream(createQuery(), - entityClass, collection); - - return new CloseableIterator() { - - @Override - public boolean hasNext() { - return stream.hasNext(); - } - - @Override - public K next() { - return stream.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Cannot remove from iterator while streaming data."); - } - - @Override - public void close() { - stream.close(); - } - }; - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.Fetchable#fetch() - */ - @Override - public List fetch() { - return find.matching(createQuery()).all(); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.Fetchable#fetchFirst() - */ - @Override - public K fetchFirst() { - return find.matching(createQuery()).firstValue(); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.Fetchable#fetchOne() - */ - @Override - public K fetchOne() { - return find.matching(createQuery()).oneValue(); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.Fetchable#fetchResults() - */ - @Override - public QueryResults fetchResults() { - - long total = fetchCount(); - return total > 0L ? new QueryResults<>(fetch(), getQueryMixin().getMetadata().getModifiers(), total) - : QueryResults.emptyResults(); - } - - /* - * (non-Javadoc) - * @see com.querydsl.core.Fetchable#fetchCount() - */ - @Override - public long fetchCount() { - return find.matching(Query.of(createQuery()).skip(-1).limit(-1)).count(); - } - - /** - * Define a join. - * - * @param ref reference - * @param target join target - * @return new instance of {@link QuerydslJoinBuilder}. - */ - public QuerydslJoinBuilder join(Path ref, Path target) { - return new QuerydslJoinBuilder<>(getQueryMixin(), ref, target); - } - - /** - * Define a join. - * - * @param ref reference - * @param target join target - * @return new instance of {@link QuerydslJoinBuilder}. - */ - public QuerydslJoinBuilder join(CollectionPathBase ref, Path target) { - return new QuerydslJoinBuilder<>(getQueryMixin(), ref, target); - } - - /** - * Define a constraint for an embedded object. - * - * @param collection collection must not be {@literal null}. - * @param target target must not be {@literal null}. - * @return new instance of {@link QuerydslAnyEmbeddedBuilder}. - */ - public QuerydslAnyEmbeddedBuilder anyEmbedded(Path> collection, Path target) { - return new QuerydslAnyEmbeddedBuilder<>(getQueryMixin(), collection); - } - - protected org.springframework.data.mongodb.core.query.Query createQuery() { - - QueryMetadata metadata = getQueryMixin().getMetadata(); - - return createQuery(createFilter(metadata), metadata.getProjection(), metadata.getModifiers(), - metadata.getOrderBy()); - } - - protected org.springframework.data.mongodb.core.query.Query createQuery(@Nullable Predicate filter, - @Nullable Expression projection, QueryModifiers modifiers, List> orderBy) { - - BasicQuery basicQuery = new BasicQuery(createQuery(filter), createProjection(projection)); - - Integer limit = modifiers.getLimitAsInteger(); - Integer offset = modifiers.getOffsetAsInteger(); - - if (limit != null) { - basicQuery.limit(limit); - } - if (offset != null) { - basicQuery.skip(offset); - } - if (orderBy.size() > 0) { - basicQuery.setSortObject(createSort(orderBy)); - } - - return basicQuery; - } - - @Nullable - protected Predicate createFilter(QueryMetadata metadata) { - - Predicate filter; - if (!metadata.getJoins().isEmpty()) { - filter = ExpressionUtils.allOf(metadata.getWhere(), createJoinFilter(metadata)); - } else { - filter = metadata.getWhere(); - } - return filter; - } - - @SuppressWarnings("unchecked") - @Nullable - protected Predicate createJoinFilter(QueryMetadata metadata) { - - LinkedMultiValueMap, Predicate> predicates = new LinkedMultiValueMap<>(); - List joins = metadata.getJoins(); - - for (int i = joins.size() - 1; i >= 0; i--) { - - JoinExpression join = joins.get(i); - Path source = (Path) ((Operation) join.getTarget()).getArg(0); - Path target = (Path) ((Operation) join.getTarget()).getArg(1); - Collection extraFilters = predicates.get(target.getRoot()); - Predicate filter = ExpressionUtils.allOf(join.getCondition(), allOf(extraFilters)); - - List ids = getIds(target.getType(), filter); - - if (ids.isEmpty()) { - return ExpressionUtils.predicate(QuerydslMongoOps.NO_MATCH, source); - } - - Path path = ExpressionUtils.path(String.class, source, "$id"); - predicates.add(source.getRoot(), ExpressionUtils.in((Path) path, ids)); - } - - Path source = (Path) ((Operation) joins.get(0).getTarget()).getArg(0); - return allOf(predicates.get(source.getRoot())); - } - - private Predicate allOf(Collection predicates) { - return predicates != null ? ExpressionUtils.allOf(predicates) : null; - } - - /** - * Fetch the list of ids matching a given condition. - * - * @param targetType must not be {@literal null}. - * @param condition must not be {@literal null}. - * @return empty {@link List} if none found. - */ - protected List getIds(Class targetType, Predicate condition) { - - Query query = createQuery(condition, null, QueryModifiers.EMPTY, Collections.emptyList()); - return mongoOperations.findDistinct(query, "_id", targetType, Object.class); - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java deleted file mode 100644 index 344ad08826..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslJoinBuilder.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018-2021 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 - * - * https://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.repository.support; - -import com.querydsl.core.JoinType; -import com.querydsl.core.support.QueryMixin; -import com.querydsl.core.types.ExpressionUtils; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.Predicate; - -/** - * {@code QuerydslJoinBuilder} is a builder for join constraints. - *

      - * Original implementation source {@link com.querydsl.mongodb.JoinBuilder} by {@literal The Querydsl Team} - * (http://www.querydsl.com/team) licensed under the Apache License, Version - * 2.0. - *

      - * Modified for usage with {@link QuerydslAbstractMongodbQuery}. - * - * @param - * @param - * @author tiwe - * @author Mark Paluch - * @author Christoph Strobl - * @since 2.1 - */ -public class QuerydslJoinBuilder, K, T> { - - private final QueryMixin queryMixin; - private final Path ref; - private final Path target; - - QuerydslJoinBuilder(QueryMixin queryMixin, Path ref, Path target) { - - this.queryMixin = queryMixin; - this.ref = ref; - this.target = target; - } - - /** - * Add the given join conditions. - * - * @param conditions must not be {@literal null}. - * @return the target {@link QueryMixin}. - * @see QueryMixin#on(Predicate) - */ - @SuppressWarnings("unchecked") - public Q on(Predicate... conditions) { - - queryMixin.addJoin(JoinType.JOIN, ExpressionUtils.as((Path) ref, target)); - queryMixin.on(conditions); - return queryMixin.getSelf(); - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java deleted file mode 100644 index 0c695afd0c..0000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoOps.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2018-2021 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 - * - * https://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.repository.support; - -import com.querydsl.core.types.Operator; - -/** - * Spring Data specific {@link Operator operators} for usage with Querydsl and MongoDB. - * - * @author Christoph Strobl - * @since 2.1 - */ -enum QuerydslMongoOps implements Operator { - - /** - * {@link Operator} always evaluating to {@literal false}. - */ - NO_MATCH(Boolean.class); - - private final Class type; - - QuerydslMongoOps(Class type) { - this.type = type; - } - - @Override - public Class getType() { - return type; - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java index 4162a79482..8b30e585e6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveSpringDataMongodbQuery.java @@ -22,6 +22,9 @@ import java.util.Collections; import java.util.List; +import org.bson.Document; + +import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithProjection; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; @@ -40,19 +43,21 @@ import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Path; import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.CollectionPathBase; +import com.querydsl.mongodb.MongodbOps; +import com.querydsl.mongodb.document.MongodbDocumentSerializer; /** * MongoDB query with utilizing {@link ReactiveMongoOperations} for command execution. * + * @implNote This class uses {@link MongoOperations} to directly convert documents into the target entity type. Also, we + * want entites to participate in lifecycle events and entity callbacks. * @param result type * @author Mark Paluch * @author Christoph Strobl * @since 2.2 */ -class ReactiveSpringDataMongodbQuery extends QuerydslAbstractMongodbQuery> { +class ReactiveSpringDataMongodbQuery extends SpringDataMongodbQuerySupport> { - private final Class entityClass; private final ReactiveMongoOperations mongoOperations; private final FindWithProjection find; @@ -60,15 +65,15 @@ class ReactiveSpringDataMongodbQuery extends QuerydslAbstractMongodbQuery entityClass, @Nullable String collection) { super(serializer); - this.entityClass = (Class) entityClass; this.mongoOperations = mongoOperations; - this.find = StringUtils.hasText(collection) ? mongoOperations.query(this.entityClass).inCollection(collection) - : mongoOperations.query(this.entityClass); + this.find = StringUtils.hasText(collection) ? mongoOperations.query((Class) entityClass).inCollection(collection) + : mongoOperations.query((Class) entityClass); } /** @@ -99,48 +104,11 @@ Mono fetchCount() { return createQuery().flatMap(it -> find.matching(it).count()); } - /** - * Define a join. - * - * @param ref reference - * @param target join target - * @return new instance of {@link QuerydslJoinBuilder}. - */ - QuerydslJoinBuilder, K, T> join(Path ref, Path target) { - return new QuerydslJoinBuilder<>(getQueryMixin(), ref, target); - } - - /** - * Define a join. - * - * @param ref reference - * @param target join target - * @return new instance of {@link QuerydslJoinBuilder}. - */ - QuerydslJoinBuilder, K, T> join(CollectionPathBase ref, - Path target) { - - return new QuerydslJoinBuilder<>(getQueryMixin(), ref, target); - } - - /** - * Define a constraint for an embedded object. - * - * @param collection collection must not be {@literal null}. - * @param target target must not be {@literal null}. - * @return new instance of {@link QuerydslAnyEmbeddedBuilder}. - */ - QuerydslAnyEmbeddedBuilder, K> anyEmbedded( - Path> collection, Path target) { - - return new QuerydslAnyEmbeddedBuilder<>(getQueryMixin(), collection); - } - protected Mono createQuery() { QueryMetadata metadata = getQueryMixin().getMetadata(); - return createQuery(createFilter(metadata), metadata.getProjection(), metadata.getModifiers(), + return createQuery(createReactiveFilter(metadata), metadata.getProjection(), metadata.getModifiers(), metadata.getOrderBy()); } @@ -160,7 +128,8 @@ protected Mono createQuery(Mono filter, @Nullable Expression { - BasicQuery basicQuery = new BasicQuery(it, createProjection(projection)); + Document fields = createProjection(projection); + BasicQuery basicQuery = new BasicQuery(it, fields == null ? new Document() : fields); Integer limit = modifiers.getLimitAsInteger(); Integer offset = modifiers.getOffsetAsInteger(); @@ -179,11 +148,11 @@ protected Mono createQuery(Mono filter, @Nullable Expression createFilter(QueryMetadata metadata) { + protected Mono createReactiveFilter(QueryMetadata metadata) { if (!metadata.getJoins().isEmpty()) { - return createJoinFilter(metadata).map(it -> ExpressionUtils.allOf(metadata.getWhere(), it)) + return createReactiveJoinFilter(metadata).map(it -> ExpressionUtils.allOf(metadata.getWhere(), it)) .switchIfEmpty(Mono.justOrEmpty(metadata.getWhere())); } @@ -197,7 +166,7 @@ protected Mono createFilter(QueryMetadata metadata) { * @return */ @SuppressWarnings("unchecked") - protected Mono createJoinFilter(QueryMetadata metadata) { + protected Mono createReactiveJoinFilter(QueryMetadata metadata) { MultiValueMap, Mono> predicates = new LinkedMultiValueMap<>(); List joins = metadata.getJoins(); @@ -230,7 +199,7 @@ protected Mono createJoinFilter(QueryMetadata metadata) { Path source = (Path) ((Operation) joins.get(0).getTarget()).getArg(0); return allOf(predicates.get(source.getRoot())).onErrorResume(NoMatchException.class, - e -> Mono.just(ExpressionUtils.predicate(QuerydslMongoOps.NO_MATCH, e.source))); + e -> Mono.just(ExpressionUtils.predicate(MongodbOps.NO_MATCH, e.source))); } private Mono allOf(@Nullable Collection> predicates) { @@ -246,8 +215,8 @@ private Mono allOf(@Nullable Collection> predicates) */ protected Flux getIds(Class targetType, Mono condition) { - return condition.flatMapMany(it -> getIds(targetType, it)) - .switchIfEmpty(Flux.defer(() -> getIds(targetType, (Predicate) null))); + return condition.flatMapMany(it -> getJoinIds(targetType, it)) + .switchIfEmpty(Flux.defer(() -> getJoinIds(targetType, (Predicate) null))); } /** @@ -257,12 +226,18 @@ protected Flux getIds(Class targetType, Mono condition) { * @param condition must not be {@literal null}. * @return empty {@link List} if none found. */ - protected Flux getIds(Class targetType, @Nullable Predicate condition) { + protected Flux getJoinIds(Class targetType, @Nullable Predicate condition) { return createQuery(Mono.justOrEmpty(condition), null, QueryModifiers.EMPTY, Collections.emptyList()) .flatMapMany(query -> mongoOperations.findDistinct(query, "_id", targetType, Object.class)); } + @Override + protected List getIds(Class aClass, Predicate predicate) { + throw new UnsupportedOperationException( + "Use create Flux getIds(Class targetType, Mono condition)"); + } + /** * Marker exception to indicate no matches for a query using reference Id's. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java index 8a153d0c2c..d62aa99c5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuery.java @@ -15,7 +15,27 @@ */ package org.springframework.data.mongodb.repository.support; +import java.util.Collections; +import java.util.List; + +import org.bson.Document; + +import org.springframework.data.mongodb.core.ExecutableFindOperation; import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.lang.Nullable; + +import com.mysema.commons.lang.CloseableIterator; +import com.mysema.commons.lang.EmptyCloseableIterator; +import com.querydsl.core.Fetchable; +import com.querydsl.core.QueryMetadata; +import com.querydsl.core.QueryModifiers; +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Expression; +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.Predicate; +import com.querydsl.mongodb.document.MongodbDocumentSerializer; /** * Spring Data specific simple {@link com.querydsl.core.Fetchable} {@link com.querydsl.core.SimpleQuery Query} @@ -25,7 +45,13 @@ * @author Mark Paluch * @author Christoph Strobl */ -public class SpringDataMongodbQuery extends QuerydslFetchableMongodbQuery> { +public class SpringDataMongodbQuery extends SpringDataMongodbQuerySupport> + implements Fetchable { + + private final Class entityClass; + private final String collection; + private final MongoOperations mongoOperations; + private final ExecutableFindOperation.FindWithProjection find; /** * Creates a new {@link SpringDataMongodbQuery}. @@ -33,7 +59,7 @@ public class SpringDataMongodbQuery extends QuerydslFetchableMongodbQuery type) { + public SpringDataMongodbQuery(MongoOperations operations, Class type) { this(operations, type, operations.getCollectionName(type)); } @@ -44,9 +70,174 @@ public SpringDataMongodbQuery(final MongoOperations operations, final Class type, + public SpringDataMongodbQuery(MongoOperations operations, Class type, String collectionName) { + this(new SpringDataMongodbSerializer(operations.getConverter()), operations, type, collectionName); + } + + private SpringDataMongodbQuery(MongodbDocumentSerializer serializer, MongoOperations operations, + Class type, String collectionName) { + + super(serializer); - super(new SpringDataMongodbSerializer(operations.getConverter()), type, collectionName, operations); + this.entityClass = (Class) type; + this.collection = collectionName; + this.mongoOperations = operations; + this.find = mongoOperations.query(this.entityClass).inCollection(collection); } + + /* + * (non-Javadoc) + * @see com.querydsl.core.Fetchable#iterable() + */ + @Override + public CloseableIterator iterate() { + + try { + org.springframework.data.util.CloseableIterator stream = mongoOperations.stream(createQuery(), + entityClass, collection); + + return new CloseableIterator() { + + @Override + public boolean hasNext() { + return stream.hasNext(); + } + + @Override + public T next() { + return stream.next(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Cannot remove from iterator while streaming data."); + } + + @Override + public void close() { + stream.close(); + } + }; + } catch (RuntimeException e) { + return handleException(e, new EmptyCloseableIterator<>()); + } + } + + /* + * (non-Javadoc) + * @see com.querydsl.core.Fetchable#fetch() + */ + @Override + public List fetch() { + try { + return find.matching(createQuery()).all(); + } catch (RuntimeException e) { + return handleException(e, Collections.emptyList()); + } + } + + /* + * (non-Javadoc) + * @see com.querydsl.core.Fetchable#fetchFirst() + */ + @Override + public T fetchFirst() { + try { + return find.matching(createQuery()).firstValue(); + } catch (RuntimeException e) { + return handleException(e, null); + } + } + + /* + * (non-Javadoc) + * @see com.querydsl.core.Fetchable#fetchOne() + */ + @Override + public T fetchOne() { + try { + return find.matching(createQuery()).oneValue(); + } catch (RuntimeException e) { + return handleException(e, null); + } + } + + /* + * (non-Javadoc) + * @see com.querydsl.core.Fetchable#fetchResults() + */ + @Override + public QueryResults fetchResults() { + + long total = fetchCount(); + return total > 0L ? new QueryResults<>(fetch(), getQueryMixin().getMetadata().getModifiers(), total) + : QueryResults.emptyResults(); + } + + /* + * (non-Javadoc) + * @see com.querydsl.core.Fetchable#fetchCount() + */ + @Override + public long fetchCount() { + try { + return find.matching(Query.of(createQuery()).skip(-1).limit(-1)).count(); + } catch (RuntimeException e) { + return handleException(e, 0L); + } + } + + protected org.springframework.data.mongodb.core.query.Query createQuery() { + + QueryMetadata metadata = getQueryMixin().getMetadata(); + + return createQuery(createFilter(metadata), metadata.getProjection(), metadata.getModifiers(), + metadata.getOrderBy()); + } + + protected org.springframework.data.mongodb.core.query.Query createQuery(@Nullable Predicate filter, + @Nullable Expression projection, QueryModifiers modifiers, List> orderBy) { + + Document fields = createProjection(projection); + BasicQuery basicQuery = new BasicQuery(createQuery(filter), fields == null ? new Document() : fields); + + Integer limit = modifiers.getLimitAsInteger(); + Integer offset = modifiers.getOffsetAsInteger(); + + if (limit != null) { + basicQuery.limit(limit); + } + if (offset != null) { + basicQuery.skip(offset); + } + if (orderBy.size() > 0) { + basicQuery.setSortObject(createSort(orderBy)); + } + + return basicQuery; + } + + /** + * Fetch the list of ids matching a given condition. + * + * @param targetType must not be {@literal null}. + * @param condition must not be {@literal null}. + * @return empty {@link List} if none found. + */ + protected List getIds(Class targetType, Predicate condition) { + + Query query = createQuery(condition, null, QueryModifiers.EMPTY, Collections.emptyList()); + return mongoOperations.findDistinct(query, "_id", targetType, Object.class); + } + + private static T handleException(RuntimeException e, T defaultValue) { + + if (e.getClass().getName().endsWith("$NoResults")) { + return defaultValue; + } + + throw e; + } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java new file mode 100644 index 0000000000..406019cf4d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java @@ -0,0 +1,147 @@ +/* + * Copyright 2021 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 + * + * https://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.repository.support; + +import java.util.List; + +import org.bson.Document; +import org.bson.codecs.DocumentCodec; +import org.bson.json.JsonMode; +import org.bson.json.JsonWriterSettings; + +import org.springframework.beans.DirectFieldAccessor; + +import com.mongodb.MongoClientSettings; +import com.querydsl.core.support.QueryMixin; +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.mongodb.document.AbstractMongodbQuery; +import com.querydsl.mongodb.document.MongodbDocumentSerializer; + +/** + * Support query type to augment Spring Data-specific {@link #toString} representations and + * {@link org.springframework.data.domain.Sort} creation. + * + * @author Mark Paluch + * @since 3.3 + */ +abstract class SpringDataMongodbQuerySupport> + extends AbstractMongodbQuery { + + private final QueryMixin superQueryMixin; + + private static final JsonWriterSettings JSON_WRITER_SETTINGS = JsonWriterSettings.builder().outputMode(JsonMode.SHELL) + .build(); + + private final MongodbDocumentSerializer serializer; + + @SuppressWarnings("unchecked") + SpringDataMongodbQuerySupport(MongodbDocumentSerializer serializer) { + super(serializer); + this.serializer = serializer; + + DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(this); + this.superQueryMixin = (QueryMixin) fieldAccessor.getPropertyValue("queryMixin"); + } + + /** + * Returns the {@literal Mongo Shell} representation of the query.
      + * The following query + * + *
      +	 *
      +	 * where(p.lastname.eq("Matthews")).orderBy(p.firstname.asc()).offset(1).limit(5);
      +	 * 
      + * + * results in + * + *
      +	 *
      +	 * find({"lastname" : "Matthews"}).sort({"firstname" : 1}).skip(1).limit(5)
      +	 * 
      + * + * Note that encoding to {@link String} may fail when using data types that cannot be encoded or DBRef's without an + * identifier. + * + * @return never {@literal null}. + */ + @Override + public String toString() { + + Document projection = createProjection(getQueryMixin().getMetadata().getProjection()); + Document sort = createSort(getQueryMixin().getMetadata().getOrderBy()); + DocumentCodec codec = new DocumentCodec(MongoClientSettings.getDefaultCodecRegistry()); + + StringBuilder sb = new StringBuilder("find(" + asDocument().toJson(JSON_WRITER_SETTINGS, codec)); + if (projection != null && projection.isEmpty()) { + sb.append(", ").append(projection.toJson(JSON_WRITER_SETTINGS, codec)); + } + sb.append(")"); + if (!sort.isEmpty()) { + sb.append(".sort(").append(sort.toJson(JSON_WRITER_SETTINGS, codec)).append(")"); + } + if (getQueryMixin().getMetadata().getModifiers().getOffset() != null) { + sb.append(".skip(").append(getQueryMixin().getMetadata().getModifiers().getOffset()).append(")"); + } + if (getQueryMixin().getMetadata().getModifiers().getLimit() != null) { + sb.append(".limit(").append(getQueryMixin().getMetadata().getModifiers().getLimit()).append(")"); + } + return sb.toString(); + } + + /** + * Get the where definition as a Document instance + * + * @return + */ + public Document asDocument() { + return createQuery(getQueryMixin().getMetadata().getWhere()); + } + + /** + * Obtain the {@literal Mongo Shell} json query representation. + * + * @return never {@literal null}. + */ + public String toJson() { + return toJson(JSON_WRITER_SETTINGS); + } + + /** + * Obtain the json query representation applying given {@link JsonWriterSettings settings}. + * + * @param settings must not be {@literal null}. + * @return never {@literal null}. + */ + public String toJson(JsonWriterSettings settings) { + return asDocument().toJson(settings); + } + + /** + * Compute the sort {@link Document} from the given list of {@link OrderSpecifier order specifiers}. + * + * @param orderSpecifiers can be {@literal null}. + * @return an empty {@link Document} if predicate is {@literal null}. + * @see MongodbDocumentSerializer#toSort(List) + */ + protected Document createSort(List> orderSpecifiers) { + return serializer.toSort(orderSpecifiers); + } + + // TODO: Remove once https://github.com/querydsl/querydsl/pull/2916 is merged + QueryMixin getQueryMixin() { + return superQueryMixin; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java index e18f30d96a..2453e1a46c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java @@ -22,6 +22,7 @@ import java.util.regex.Pattern; import org.bson.Document; + import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -39,6 +40,7 @@ import com.querydsl.core.types.PathMetadata; import com.querydsl.core.types.PathType; import com.querydsl.mongodb.MongodbSerializer; +import com.querydsl.mongodb.document.MongodbDocumentSerializer; /** * Custom {@link MongodbSerializer} to take mapping information into account when building keys for constraints. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java index 5584ae6e3b..0067eb3bf1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java @@ -28,8 +28,6 @@ import java.util.Arrays; -import javax.annotation.Nullable; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -49,6 +47,7 @@ import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactory; import org.springframework.data.mongodb.repository.support.SimpleReactiveMongoRepository; import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; +import org.springframework.lang.Nullable; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.util.ClassUtils; From d57c5a952984e39fda28d2807e7ac41ae2eb162f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 15 Jun 2021 16:51:28 +0200 Subject: [PATCH 0461/1381] Add support for Wildcard Index. Add WildcardIndexed annotation and the programatic WildcardIndex. Closes #3225 Original pull request: #3671. --- .../data/mongodb/core/IndexConverters.java | 4 + .../data/mongodb/core/index/IndexField.java | 25 ++- .../data/mongodb/core/index/IndexInfo.java | 26 +++ .../MongoPersistentEntityIndexResolver.java | 106 ++++++++-- .../mongodb/core/index/WildcardIndex.java | 198 ++++++++++++++++++ .../mongodb/core/index/WildcardIndexed.java | 130 ++++++++++++ .../core/index/IndexInfoUnitTests.java | 11 + ...ersistentEntityIndexResolverUnitTests.java | 85 +++++++- src/main/asciidoc/reference/mapping.adoc | 88 ++++++++ 9 files changed, 654 insertions(+), 19 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java index e7fae4df5c..4d5349f7e7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java @@ -115,6 +115,10 @@ private static Converter getIndexDefinitionIndexO ops = ops.collation(fromDocument(indexOptions.get("collation", Document.class))); } + if(indexOptions.containsKey("wildcardProjection")) { + ops.wildcardProjection(indexOptions.get("wildcardProjection", Document.class)); + } + return ops; }; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java index d0a1da68ea..7883da2270 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java @@ -29,7 +29,7 @@ public final class IndexField { enum Type { - GEO, TEXT, DEFAULT, HASH; + GEO, TEXT, DEFAULT, HASH, WILDCARD; } private final String key; @@ -48,7 +48,7 @@ private IndexField(String key, @Nullable Direction direction, @Nullable Type typ if (Type.GEO.equals(type) || Type.TEXT.equals(type)) { Assert.isNull(direction, "Geo/Text indexes must not have a direction!"); } else { - if (!Type.HASH.equals(type)) { + if (!(Type.HASH.equals(type) || Type.WILDCARD.equals(type))) { Assert.notNull(direction, "Default indexes require a direction"); } } @@ -77,6 +77,17 @@ static IndexField hashed(String key) { return new IndexField(key, null, Type.HASH); } + /** + * Creates a {@literal wildcard} {@link IndexField} for the given key. + * + * @param key must not be {@literal null} or empty. + * @return new instance of {@link IndexField}. + * @since 3.3 + */ + static IndexField wildcard(String key) { + return new IndexField(key, null, Type.WILDCARD); + } + /** * Creates a geo {@link IndexField} for the given key. * @@ -142,6 +153,16 @@ public boolean isHashed() { return Type.HASH.equals(type); } + /** + * Returns whether the {@link IndexField} is contains a {@literal wildcard} expression. + * + * @return {@literal true} if {@link IndexField} contains a wildcard {@literal $**}. + * @since 3.3 + */ + public boolean isWildcard() { + return Type.WILDCARD.equals(type); + } + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java index 7b507a8727..f8370b1bc6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java @@ -55,6 +55,7 @@ public class IndexInfo { private @Nullable Duration expireAfter; private @Nullable String partialFilterExpression; private @Nullable Document collation; + private @Nullable Document wildcardProjection; public IndexInfo(List indexFields, String name, boolean unique, boolean sparse, String language) { @@ -99,6 +100,8 @@ public static IndexInfo indexInfoOf(Document sourceDocument) { if (ObjectUtils.nullSafeEquals("hashed", value)) { indexFields.add(IndexField.hashed(key)); + } else if (key.contains("$**")) { + indexFields.add(IndexField.wildcard(key)); } else { Double keyValue = new Double(value.toString()); @@ -131,6 +134,10 @@ public static IndexInfo indexInfoOf(Document sourceDocument) { info.expireAfter = Duration.ofSeconds(NumberUtils.convertNumberToTargetClass(expireAfterSeconds, Long.class)); } + if (sourceDocument.containsKey("wildcardProjection")) { + info.wildcardProjection = sourceDocument.get("wildcardProjection", Document.class); + } + return info; } @@ -216,6 +223,16 @@ public Optional getCollation() { return Optional.ofNullable(collation); } + /** + * Get {@literal wildcardProjection} information. + * + * @return {@link Optional#empty() empty} if not set. + * @since 3.3 + */ + public Optional getWildcardProjection() { + return Optional.ofNullable(wildcardProjection); + } + /** * Get the duration after which documents within the index expire. * @@ -234,6 +251,14 @@ public boolean isHashed() { return getIndexFields().stream().anyMatch(IndexField::isHashed); } + /** + * @return {@literal true} if a wildcard index field is present. + * @since 3.3 + */ + public boolean isWildcard() { + return getIndexFields().stream().anyMatch(IndexField::isWildcard); + } + @Override public String toString() { @@ -303,4 +328,5 @@ public boolean equals(Object obj) { } return true; } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index 2fc63fb36c..78f895e077 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -46,6 +46,7 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.mongodb.util.DotPath; import org.springframework.data.spel.EvaluationContextProvider; @@ -121,6 +122,7 @@ public List resolveIndexForEntity(MongoPersistentEntity indexInformation = new ArrayList<>(); String collection = root.getCollection(); indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions("", collection, root)); + indexInformation.addAll(potentiallyCreateWildcardIndexDefinitions("", collection, root)); indexInformation.addAll(potentiallyCreateTextIndexDefinition(root, collection)); root.doWithProperties((PropertyHandler) property -> this @@ -162,17 +164,18 @@ private void potentiallyAddIndexForProperty(MongoPersistentEntity root, Mongo * @return List of {@link IndexDefinitionHolder} representing indexes for given type and its referenced property * types. Will never be {@code null}. */ - private List resolveIndexForClass( TypeInformation type, String dotPath, - Path path, String collection, CycleGuard guard) { + private List resolveIndexForClass(TypeInformation type, String dotPath, Path path, + String collection, CycleGuard guard) { return resolveIndexForEntity(mappingContext.getRequiredPersistentEntity(type), dotPath, path, collection, guard); } - private List resolveIndexForEntity(MongoPersistentEntity entity, String dotPath, - Path path, String collection, CycleGuard guard) { + private List resolveIndexForEntity(MongoPersistentEntity entity, String dotPath, Path path, + String collection, CycleGuard guard) { List indexInformation = new ArrayList<>(); indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions(dotPath, collection, entity)); + indexInformation.addAll(potentiallyCreateWildcardIndexDefinitions(dotPath, collection, entity)); entity.doWithProperties((PropertyHandler) property -> this .guardAndPotentiallyAddIndexForProperty(property, dotPath, path, collection, indexInformation, guard)); @@ -196,15 +199,15 @@ private void guardAndPotentiallyAddIndexForProperty(MongoPersistentProperty pers if (persistentProperty.isEntity()) { try { - indexes.addAll(resolveIndexForEntity(mappingContext.getPersistentEntity(persistentProperty), propertyDotPath.toString(), - propertyPath, collection, guard)); + indexes.addAll(resolveIndexForEntity(mappingContext.getPersistentEntity(persistentProperty), + propertyDotPath.toString(), propertyPath, collection, guard)); } catch (CyclicPropertyReferenceException e) { LOGGER.info(e.getMessage()); } } - List indexDefinitions = createIndexDefinitionHolderForProperty(propertyDotPath.toString(), collection, - persistentProperty); + List indexDefinitions = createIndexDefinitionHolderForProperty(propertyDotPath.toString(), + collection, persistentProperty); if (!indexDefinitions.isEmpty()) { indexes.addAll(indexDefinitions); @@ -232,6 +235,11 @@ private List createIndexDefinitionHolderForProperty(Strin if (persistentProperty.isAnnotationPresent(HashIndexed.class)) { indices.add(createHashedIndexDefinition(dotPath, collection, persistentProperty)); } + if (persistentProperty.isAnnotationPresent(WildcardIndexed.class)) { + indices.add(createWildcardIndexDefinition(dotPath, collection, + persistentProperty.getRequiredAnnotation(WildcardIndexed.class), + mappingContext.getPersistentEntity(persistentProperty))); + } return indices; } @@ -246,6 +254,18 @@ private List potentiallyCreateCompoundIndexDefinitions(St return createCompoundIndexDefinitions(dotPath, collection, entity); } + private List potentiallyCreateWildcardIndexDefinitions(String dotPath, String collection, + MongoPersistentEntity entity) { + + if (entity.findAnnotation(WildcardIndexed.class) == null) { + return Collections.emptyList(); + } + + return Collections.singletonList(new IndexDefinitionHolder(dotPath, + createWildcardIndexDefinition(dotPath, collection, entity.getRequiredAnnotation(WildcardIndexed.class), entity), + collection)); + } + private Collection potentiallyCreateTextIndexDefinition( MongoPersistentEntity root, String collection) { @@ -292,9 +312,8 @@ private Collection potentiallyCreateTextIndexDe } - private void appendTextIndexInformation(DotPath dotPath, Path path, - TextIndexDefinitionBuilder indexDefinitionBuilder, MongoPersistentEntity entity, - TextIndexIncludeOptions includeOptions, CycleGuard guard) { + private void appendTextIndexInformation(DotPath dotPath, Path path, TextIndexDefinitionBuilder indexDefinitionBuilder, + MongoPersistentEntity entity, TextIndexIncludeOptions includeOptions, CycleGuard guard) { entity.doWithProperties(new PropertyHandler() { @@ -311,8 +330,7 @@ public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) if (includeOptions.isForce() || indexed != null || persistentProperty.isEntity()) { - DotPath propertyDotPath = dotPath - .append(persistentProperty.getFieldName()); + DotPath propertyDotPath = dotPath.append(persistentProperty.getFieldName()); Path propertyPath = path.append(persistentProperty); @@ -406,6 +424,32 @@ protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, St return new IndexDefinitionHolder(dotPath, indexDefinition, collection); } + protected IndexDefinitionHolder createWildcardIndexDefinition(String dotPath, String collection, + WildcardIndexed index, @Nullable MongoPersistentEntity entity) { + + WildcardIndex indexDefinition = new WildcardIndex(dotPath); + + if (StringUtils.hasText(index.wildcardProjection())) { + indexDefinition.wildcardProjection(evaluateWildcardProjection(index.wildcardProjection(), entity)); + } + + if (!index.useGeneratedName()) { + indexDefinition.named(pathAwareIndexName(index.name(), dotPath, entity, null)); + } + + if (StringUtils.hasText(index.partialFilter())) { + indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), entity)); + } + + if (StringUtils.hasText(index.collation())) { + indexDefinition.collation(evaluateCollation(index.collation(), entity)); + } else if (entity != null && entity.hasCollation()) { + indexDefinition.collation(entity.getCollation()); + } + + return new IndexDefinitionHolder(dotPath, indexDefinition, collection); + } + private org.bson.Document resolveCompoundIndexKeyFromStringDefinition(String dotPath, String keyDefinitionString, PersistentEntity entity) { @@ -510,6 +554,33 @@ private PartialIndexFilter evaluatePartialFilter(String filterExpression, Persis return PartialIndexFilter.of(BsonUtils.parse(filterExpression, null)); } + private org.bson.Document evaluateWildcardProjection(String projectionExpression, PersistentEntity entity) { + + Object result = evaluate(projectionExpression, getEvaluationContextForProperty(entity)); + + if (result instanceof org.bson.Document) { + return (org.bson.Document) result; + } + + return BsonUtils.parse(projectionExpression, null); + } + + private Collation evaluateCollation(String collationExpression, PersistentEntity entity) { + + Object result = evaluate(collationExpression, getEvaluationContextForProperty(entity)); + if (result instanceof org.bson.Document) { + return Collation.from((org.bson.Document) result); + } + if (result instanceof Collation) { + return (Collation) result; + } + if (result instanceof String) { + return Collation.parse(result.toString()); + } + throw new IllegalStateException("Cannot parse collation " + result); + + } + /** * Creates {@link HashedIndex} wrapped in {@link IndexDefinitionHolder} out of {@link HashIndexed} for a given * {@link MongoPersistentProperty}. @@ -657,8 +728,8 @@ private void resolveAndAddIndexesForAssociation(Association indexDefinitions = createIndexDefinitionHolderForProperty(propertyDotPath.toString(), collection, - property); + List indexDefinitions = createIndexDefinitionHolderForProperty(propertyDotPath.toString(), + collection, property); if (!indexDefinitions.isEmpty()) { indexes.addAll(indexDefinitions); @@ -998,6 +1069,11 @@ public org.bson.Document getIndexKeys() { public org.bson.Document getIndexOptions() { return indexDefinition.getIndexOptions(); } + + @Override + public String toString() { + return "IndexDefinitionHolder{" + "indexKeys=" + getIndexKeys() + '}'; + } } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java new file mode 100644 index 0000000000..ab1cda6183 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java @@ -0,0 +1,198 @@ +/* + * Copyright 2021 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 + * + * https://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.index; + +import java.time.Duration; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.bson.Document; +import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +/** + * {@link WildcardIndex} is a specific {@link Index} that can be used to include all fields into an index based on the + * {@code $**" : 1} pattern on a root object (the one typically carrying the + * {@link org.springframework.data.mongodb.core.mapping.Document} annotation). On those it is possible to use + * {@link #wildcardProjectionInclude(String...)} and {@link #wildcardProjectionExclude(String...)} to define specific + * paths for in-/exclusion. + *

      + * It can also be used to define an index on a specific field path and its subfields, e.g. + * {@code "path.to.field.$**" : 1}.
      + * Note that {@literal wildcardProjections} are not allowed in this case. + *

      + * LIMITATIONS
      + *

        + *
      • {@link #unique() Unique} and {@link #expire(long) ttl} options are not supported.
      • + *
      • Keys used for sharding must not be included
      • + *
      • Cannot be used to generate any type of geo index.
      • + *
      + * + * @author Christoph Strobl + * @see MongoDB Reference Documentation: Wildcard + * Indexes/ + * @since 3.3 + */ +public class WildcardIndex extends Index { + + private @Nullable String fieldName; + private Map wildcardProjection = new LinkedHashMap<>(); + + /** + * Create a new instance of {@link WildcardIndex} using {@code $**}. + */ + public WildcardIndex() {} + + /** + * Create a new instance of {@link WildcardIndex} for the given {@literal path}. If no {@literal path} is provided the + * index will be considered a root one using {@code $**}.
      + * NOTE {@link #wildcardProjectionInclude(String...)}, {@link #wildcardProjectionExclude(String...)} + * can only be used for top level index definitions having an {@literal empty} or {@literal null} path. + * + * @param path can be {@literal null}. If {@literal null} all fields will be indexed. + */ + public WildcardIndex(@Nullable String path) { + this.fieldName = path; + } + + /** + * Include the {@code _id} field in {@literal wildcardProjection}. + * + * @return this. + */ + public WildcardIndex includeId() { + + wildcardProjection.put("_id", 1); + return this; + } + + /** + * Set the index name to use. + * + * @param name + * @return this. + */ + @Override + public WildcardIndex named(String name) { + + super.named(name); + return this; + } + + /** + * Unique option is not supported. + * + * @throws UnsupportedOperationException + */ + @Override + public Index unique() { + throw new UnsupportedOperationException("Wildcard Index does not support 'unique'."); + } + + /** + * ttl option is not supported. + * + * @throws UnsupportedOperationException + */ + @Override + public Index expire(long seconds) { + throw new UnsupportedOperationException("Wildcard Index does not support 'ttl'."); + } + + /** + * ttl option is not supported. + * + * @throws UnsupportedOperationException + */ + @Override + public Index expire(long value, TimeUnit timeUnit) { + throw new UnsupportedOperationException("Wildcard Index does not support 'ttl'."); + } + + /** + * ttl option is not supported. + * + * @throws UnsupportedOperationException + */ + @Override + public Index expire(Duration duration) { + throw new UnsupportedOperationException("Wildcard Index does not support 'ttl'."); + } + + /** + * Add fields to be included from indexing via {@code wildcardProjection}.
      + * This option is only allowed on {@link WildcardIndex#WildcardIndex() top level} wildcard indexes. + * + * @param paths must not be {@literal null}. + * @return this. + */ + public WildcardIndex wildcardProjectionInclude(String... paths) { + + for (String path : paths) { + wildcardProjection.put(path, 1); + } + return this; + } + + /** + * Add fields to be excluded from indexing via {@code wildcardProjection}.
      + * This option is only allowed on {@link WildcardIndex#WildcardIndex() top level} wildcard indexes. + * + * @param paths must not be {@literal null}. + * @return this. + */ + public WildcardIndex wildcardProjectionExclude(String... paths) { + + for (String path : paths) { + wildcardProjection.put(path, 0); + } + return this; + } + + /** + * Set the fields to be in-/excluded from indexing via {@code wildcardProjection}.
      + * This option is only allowed on {@link WildcardIndex#WildcardIndex() top level} wildcard indexes. + * + * @param includeExclude must not be {@literal null}. + * @return this. + */ + public WildcardIndex wildcardProjection(Map includeExclude) { + + wildcardProjection.putAll(includeExclude); + return this; + } + + private String getTargetFieldName() { + return StringUtils.hasText(fieldName) ? (fieldName + ".$**") : "$**"; + } + + @Override + public Document getIndexKeys() { + return new Document(getTargetFieldName(), 1); + } + + @Override + public Document getIndexOptions() { + + Document options = new Document(super.getIndexOptions()); + if (!CollectionUtils.isEmpty(wildcardProjection)) { + options.put("wildcardProjection", new Document(wildcardProjection)); + } + return options; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java new file mode 100644 index 0000000000..5f32aaf45c --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java @@ -0,0 +1,130 @@ +/* + * Copyright 2021 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 + * + * https://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.index; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for an entity or property that should be used as key for a + * Wildcard Index.
      + * If placed on a {@link ElementType#TYPE type} that is a root level domain entity (one having an + * {@link org.springframework.data.mongodb.core.mapping.Document} annotation) will advise the index creator to create a + * wildcard index for it. + * + *
      + *
      + * @Document
      + * @WildcardIndexed
      + * public class Product {
      + *     ...
      + * }
      + *
      + * db.product.createIndex({ "$**" : 1 } , {})
      + * 
      + * + * {@literal wildcardProjection} can be used to specify keys to in-/exclude in the index. + * + *
      + *
      + * @Document
      + * @WildcardIndexed(wildcardProjection = "{ 'userMetadata.age' : 0 }")
      + * public class User {
      + *     private @Id String id;
      + *     private UserMetadata userMetadata;
      + * }
      + *
      + *
      + * db.user.createIndex(
      + *   { "$**" : 1 },
      + *   { "wildcardProjection" :
      + *     { "userMetadata.age" : 0 }
      + *   }
      + * )
      + * 
      + * + * Wildcard indexes can also be expressed by adding the annotation directly to the field. Please note that + * {@literal wildcardProjection} is not allowed on nested paths. + * + *
      + * @Document
      + * public class User {
      + * 
      + *     private @Id String id;
      + *
      + *     @WildcardIndexed
      + *     private UserMetadata userMetadata;
      + * }
      + *
      + *
      + * db.user.createIndex({ "userMetadata.$**" : 1 }, {})
      + * 
      + * + * @author Christoph Strobl + * @since 3.3 + */ +@Documented +@Target({ ElementType.TYPE, ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface WildcardIndexed { + + /** + * Index name either as plain value or as {@link org.springframework.expression.spel.standard.SpelExpression template + * expression}.
      + *
      + * The name will only be applied as is when defined on root level. For usage on nested or embedded structures the + * provided name will be prefixed with the path leading to the entity.
      + * + * @return + */ + String name() default ""; + + /** + * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults + * to {@literal false}. + * + * @return {@literal false} by default. + */ + boolean useGeneratedName() default false; + + /** + * Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}.
      + * + * @return empty by default. + * @see https://docs.mongodb.com/manual/core/index-partial/ + */ + String partialFilter() default ""; + + /** + * Explicitly specify sub fields to be in-/excluded as a {@link org.bson.Document#parse(String) prasable} String. + *
      + * NOTE: Can only be done on root level documents. + * + * @return empty by default. + */ + String wildcardProjection() default ""; + + /** + * Defines the collation to apply. + * + * @return an empty {@link String} by default. + */ + String collation() default ""; +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java index 2026dfc644..3618e4c1f9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java @@ -36,6 +36,7 @@ public class IndexInfoUnitTests { static final String INDEX_WITH_PARTIAL_FILTER = "{ \"v\" : 2, \"key\" : { \"k3y\" : 1 }, \"name\" : \"partial-filter-index\", \"ns\" : \"db.collection\", \"partialFilterExpression\" : { \"quantity\" : { \"$gte\" : 10 } } }"; static final String INDEX_WITH_EXPIRATION_TIME = "{ \"v\" : 2, \"key\" : { \"lastModifiedDate\" : 1 },\"name\" : \"expire-after-last-modified\", \"ns\" : \"db.collectio\", \"expireAfterSeconds\" : 3600 }"; static final String HASHED_INDEX = "{ \"v\" : 2, \"key\" : { \"score\" : \"hashed\" }, \"name\" : \"score_hashed\", \"ns\" : \"db.collection\" }"; + static final String WILDCARD_INDEX = "{ \"v\" : 2, \"key\" : { \"$**\" : 1 }, \"name\" : \"$**_1\", \"wildcardProjection\" : { \"fieldA\" : 0, \"fieldB.fieldC\" : 0 } }"; @Test public void isIndexForFieldsCorrectly() { @@ -79,6 +80,16 @@ public void hashedIndexIsMarkedAsSuch() { assertThat(getIndexInfo(HASHED_INDEX).isHashed()).isTrue(); } + @Test // GH-3225 + public void identifiesWildcardIndexCorrectly() { + assertThat(getIndexInfo(WILDCARD_INDEX).isWildcard()).isTrue(); + } + + @Test // GH-3225 + public void readsWildcardIndexProjectionCorrectly() { + assertThat(getIndexInfo(WILDCARD_INDEX).getWildcardProjection()).contains(new Document("fieldA", 0).append("fieldB.fieldC", 0)); + } + private static IndexInfo getIndexInfo(String documentJson) { return IndexInfo.indexInfoOf(Document.parse(documentJson)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 489070548d..0a06561b67 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -15,8 +15,9 @@ */ package org.springframework.data.mongodb.core.index; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; -import static org.springframework.data.mongodb.test.util.Assertions.*; +import static org.springframework.data.mongodb.test.util.Assertions.assertThatExceptionOfType; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -25,6 +26,7 @@ import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; @@ -1323,6 +1325,49 @@ public void errorsOnIndexOnEmbedded() { } + @Test // GH-3225 + public void resolvesWildcardOnRoot() { + + List indices = prepareMappingContextAndResolveIndexForType( + WithWildCardIndexOnEntity.class); + assertThat(indices).hasSize(1); + assertThat(indices.get(0)).satisfies(it -> { + assertThat(it.getIndexKeys()).containsEntry("$**", 1); + }); + } + + @Test // GH-3225 + public void resolvesWildcardOnProperty() { + + List indices = prepareMappingContextAndResolveIndexForType( + WithWildCardIndexOnProperty.class); + assertThat(indices).hasSize(3); + assertThat(indices.get(0)).satisfies(it -> { + assertThat(it.getIndexKeys()).containsEntry("value.$**", 1); + }); + assertThat(indices.get(1)).satisfies(it -> { + assertThat(it.getIndexKeys()).containsEntry("the_field.$**", 1); + }); + assertThat(indices.get(2)).satisfies(it -> { + assertThat(it.getIndexKeys()).containsEntry("withOptions.$**", 1); + assertThat(it.getIndexOptions()).containsEntry("name", + "withOptions.idx") + .containsEntry("collation", new org.bson.Document("locale", "en_US")) + .containsEntry("partialFilterExpression", new org.bson.Document("$eq", 1)); + }); + } + + @Test // GH-3225 + public void resolvesWildcardTypeOfNestedProperty() { + + List indices = prepareMappingContextAndResolveIndexForType( + WithWildCardOnEntityOfNested.class); + assertThat(indices).hasSize(1); + assertThat(indices.get(0)).satisfies(it -> { + assertThat(it.getIndexKeys()).containsEntry("value.$**", 1); + }); + } + @Document class MixedIndexRoot { @@ -1533,7 +1578,7 @@ class InvalidIndexOnUnwrapped { @Indexed // @Unwrapped.Nullable // - UnwrappableType unwrappableType; + UnwrappableType unwrappableType; } @@ -1573,6 +1618,42 @@ class WithHashedIndex { @HashIndexed String value; } + @Document + @WildcardIndexed + class WithWildCardIndexOnEntity { + + String value; + } + + @Document + @WildcardIndexed(wildcardProjection = "{'_id' : 1, 'value' : 0}") + class WithWildCardIndexHavingProjectionOnEntity { + + String value; + } + + @Document + class WithWildCardIndexOnProperty { + + @WildcardIndexed // + Map value; + + @WildcardIndexed // + @Field("the_field") // + Map renamedField; + + @WildcardIndexed(name = "idx", partialFilter = "{ '$eq' : 1 }", collation = "en_US") // + Map withOptions; + + } + + @Document + class WithWildCardOnEntityOfNested { + + WithWildCardIndexOnEntity value; + + } + @Document class WithHashedIndexAndIndex { diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index f08d03d3f0..7caf1093b9 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -760,6 +760,94 @@ mongoOperations.indexOpsFor(Jedi.class) ---- ==== +[[mapping-usage-indexes.wildcard-index]] +=== Wildcard Indexes + +A `WildcardIndex` is an index that can be used to include all fields or specific ones based a given (wildcard) pattern. +For details, refer to the https://docs.mongodb.com/manual/core/index-wildcard/[MongoDB Documentation]. + +The index can be set up programmatically using `WildcardIndex` via `IndexOperations`. + +.Programmatic WildcardIndex setup +==== +[source,java] +---- +mongoOperations + .indexOps(User.class) + .ensureIndex(new WildcardIndex("userMetadata")); +---- +[source,javascript] +---- +db.user.createIndex({ "userMetadata.$**" : 1 }, {}) +---- +==== + +The `@WildcardIndex` annotation allows a declarative index setup an can be added on either a type or property. + +If placed on a type that is a root level domain entity (one having an `@Document` annotation) will advise the index creator to create a +wildcard index for it. + +.Wildcard index on domain type +==== +[source,java] +---- +@Document +@WildcardIndexed +public class Product { + ... +} +---- +[source,javascript] +---- +db.product.createIndex({ "$**" : 1 },{}) +---- +==== + +The `wildcardProjection` can be used to specify keys to in-/exclude in the index. + +.Wildcard index with `wildcardProjection` +==== +[source,java] +---- +@Document +@WildcardIndexed(wildcardProjection = "{ 'userMetadata.age' : 0 }") +public class User { + private @Id String id; + private UserMetadata userMetadata; +} +---- +[source,javascript] +---- +db.user.createIndex( + { "$**" : 1 }, + { "wildcardProjection" : + { "userMetadata.age" : 0 } + } +) +---- +==== + +Wildcard indexes can also be expressed by adding the annotation directly to the field. +Please note that `wildcardProjection` is not allowed on nested paths. + +.Wildcard index on property +==== +[source,java] +---- +@Document +public class User { + private @Id String id; + + @WildcardIndexed + private UserMetadata userMetadata; +} +---- +[source,javascript] +---- +db.user.createIndex({ "userMetadata.$**" : 1 }, {}) +---- +==== + [[mapping-usage-indexes.text-index]] === Text Indexes From f3b90c2b8abf760d503115f4569b5e57bd6beb8e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 14 Jul 2021 15:03:39 +0200 Subject: [PATCH 0462/1381] Polishing. Reformat code. Tweak javadoc. Reject wildcard projection usage on properties with a MappingException. Omit wildcard projections when declared on document types that are used as subdocument. See #3225 Original pull request: #3671. --- .../data/mongodb/core/IndexConverters.java | 2 +- .../data/mongodb/core/index/IndexField.java | 15 +++++++-- .../data/mongodb/core/index/IndexInfo.java | 2 +- .../MongoPersistentEntityIndexResolver.java | 24 ++++++++++++-- .../mongodb/core/index/WildcardIndex.java | 10 +++--- .../mongodb/core/index/WildcardIndexed.java | 14 ++++---- ...ersistentEntityIndexResolverUnitTests.java | 33 ++++++++++++++++++- src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/reference/mapping.adoc | 9 ++--- 9 files changed, 87 insertions(+), 23 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java index 4d5349f7e7..db1fa0bf80 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/IndexConverters.java @@ -115,7 +115,7 @@ private static Converter getIndexDefinitionIndexO ops = ops.collation(fromDocument(indexOptions.get("collation", Document.class))); } - if(indexOptions.containsKey("wildcardProjection")) { + if (indexOptions.containsKey("wildcardProjection")) { ops.wildcardProjection(indexOptions.get("wildcardProjection", Document.class)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java index 7883da2270..843584b29d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexField.java @@ -29,7 +29,17 @@ public final class IndexField { enum Type { - GEO, TEXT, DEFAULT, HASH, WILDCARD; + GEO, TEXT, DEFAULT, + + /** + * @since 2.2 + */ + HASH, + + /** + * @since 3.3 + */ + WILDCARD; } private final String key; @@ -78,7 +88,8 @@ static IndexField hashed(String key) { } /** - * Creates a {@literal wildcard} {@link IndexField} for the given key. + * Creates a {@literal wildcard} {@link IndexField} for the given key. The {@code key} must follow the + * {@code fieldName.$**} notation. * * @param key must not be {@literal null} or empty. * @return new instance of {@link IndexField}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java index f8370b1bc6..51b4aa48cf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java @@ -100,7 +100,7 @@ public static IndexInfo indexInfoOf(Document sourceDocument) { if (ObjectUtils.nullSafeEquals("hashed", value)) { indexFields.add(IndexField.hashed(key)); - } else if (key.contains("$**")) { + } else if (key.endsWith("$**")) { indexFields.add(IndexField.wildcard(key)); } else { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index 78f895e077..5fdb1cbc40 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -119,6 +119,8 @@ public List resolveIndexForEntity(MongoPersistentEntity String .format("Entity %s is not a collection root. Make sure to annotate it with @Document!", root.getName())); + verifyWildcardIndexedProjection(root); + List indexInformation = new ArrayList<>(); String collection = root.getCollection(); indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions("", collection, root)); @@ -133,6 +135,24 @@ public List resolveIndexForEntity(MongoPersistentEntity entity) { + + entity.doWithAll(it -> { + + if (it.isAnnotationPresent(WildcardIndexed.class)) { + + WildcardIndexed indexed = it.getRequiredAnnotation(WildcardIndexed.class); + + if (!ObjectUtils.isEmpty(indexed.wildcardProjection())) { + + throw new MappingException(String.format( + "WildcardIndexed.wildcardProjection cannot be used on nested paths. Offending property: %s.%s", + entity.getName(), it.getName())); + } + } + }); + } + private void potentiallyAddIndexForProperty(MongoPersistentEntity root, MongoPersistentProperty persistentProperty, List indexes, CycleGuard guard) { @@ -257,7 +277,7 @@ private List potentiallyCreateCompoundIndexDefinitions(St private List potentiallyCreateWildcardIndexDefinitions(String dotPath, String collection, MongoPersistentEntity entity) { - if (entity.findAnnotation(WildcardIndexed.class) == null) { + if (!entity.isAnnotationPresent(WildcardIndexed.class)) { return Collections.emptyList(); } @@ -429,7 +449,7 @@ protected IndexDefinitionHolder createWildcardIndexDefinition(String dotPath, St WildcardIndex indexDefinition = new WildcardIndex(dotPath); - if (StringUtils.hasText(index.wildcardProjection())) { + if (StringUtils.hasText(index.wildcardProjection()) && ObjectUtils.isEmpty(dotPath)) { indexDefinition.wildcardProjection(evaluateWildcardProjection(index.wildcardProjection(), entity)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java index ab1cda6183..b07c3b1bc9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndex.java @@ -51,7 +51,7 @@ public class WildcardIndex extends Index { private @Nullable String fieldName; - private Map wildcardProjection = new LinkedHashMap<>(); + private final Map wildcardProjection = new LinkedHashMap<>(); /** * Create a new instance of {@link WildcardIndex} using {@code $**}. @@ -97,7 +97,7 @@ public WildcardIndex named(String name) { /** * Unique option is not supported. * - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException not supported for wildcard indexes. */ @Override public Index unique() { @@ -107,7 +107,7 @@ public Index unique() { /** * ttl option is not supported. * - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException not supported for wildcard indexes. */ @Override public Index expire(long seconds) { @@ -117,7 +117,7 @@ public Index expire(long seconds) { /** * ttl option is not supported. * - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException not supported for wildcard indexes. */ @Override public Index expire(long value, TimeUnit timeUnit) { @@ -127,7 +127,7 @@ public Index expire(long value, TimeUnit timeUnit) { /** * ttl option is not supported. * - * @throws UnsupportedOperationException + * @throws UnsupportedOperationException not supported for wildcard indexes. */ @Override public Index expire(Duration duration) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java index 5f32aaf45c..d1b18e85bf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/WildcardIndexed.java @@ -38,7 +38,7 @@ * * db.product.createIndex({ "$**" : 1 } , {}) * - * + * * {@literal wildcardProjection} can be used to specify keys to in-/exclude in the index. * *
      @@ -65,7 +65,7 @@
        * 
        * @Document
        * public class User {
      - * 
      + *
        *     private @Id String id;
        *
        *     @WildcardIndexed
      @@ -89,9 +89,9 @@
       	 * expression}. 
      *
      * The name will only be applied as is when defined on root level. For usage on nested or embedded structures the - * provided name will be prefixed with the path leading to the entity.
      - * - * @return + * provided name will be prefixed with the path leading to the entity. + * + * @return empty by default. */ String name() default ""; @@ -115,8 +115,8 @@ /** * Explicitly specify sub fields to be in-/excluded as a {@link org.bson.Document#parse(String) prasable} String. *
      - * NOTE: Can only be done on root level documents. - * + * NOTE: Can only be applied on root level documents. + * * @return empty by default. */ String wildcardProjection() default ""; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 0a06561b67..30f6a9bfc5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -32,10 +32,12 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; + import org.springframework.core.annotation.AliasFor; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.annotation.Id; import org.springframework.data.geo.Point; +import org.springframework.data.mapping.MappingException; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolverUnitTests.CompoundIndexResolutionTests; @@ -1333,6 +1335,20 @@ public void resolvesWildcardOnRoot() { assertThat(indices).hasSize(1); assertThat(indices.get(0)).satisfies(it -> { assertThat(it.getIndexKeys()).containsEntry("$**", 1); + assertThat(it.getIndexOptions()).isEmpty(); + }); + } + + @Test // GH-3225 + public void resolvesWildcardWithProjectionOnRoot() { + + List indices = prepareMappingContextAndResolveIndexForType( + WithWildCardIndexHavingProjectionOnEntity.class); + assertThat(indices).hasSize(1); + assertThat(indices.get(0)).satisfies(it -> { + assertThat(it.getIndexKeys()).containsEntry("$**", 1); + assertThat(it.getIndexOptions()).containsEntry("wildcardProjection", + org.bson.Document.parse("{'_id' : 1, 'value' : 0}")); }); } @@ -1365,6 +1381,15 @@ public void resolvesWildcardTypeOfNestedProperty() { assertThat(indices).hasSize(1); assertThat(indices.get(0)).satisfies(it -> { assertThat(it.getIndexKeys()).containsEntry("value.$**", 1); + assertThat(it.getIndexOptions()).hasSize(1).containsKey("name"); + }); + } + + @Test // GH-3225 + public void rejectsWildcardProjectionOnNestedPaths() { + + assertThatExceptionOfType(MappingException.class).isThrownBy(() -> { + prepareMappingContextAndResolveIndexForType(WildcardIndexedProjectionOnNestedPath.class); }); } @@ -1647,10 +1672,16 @@ class WithWildCardIndexOnProperty { } + @Document + class WildcardIndexedProjectionOnNestedPath { + + @WildcardIndexed(wildcardProjection = "{}") String foo; + } + @Document class WithWildCardOnEntityOfNested { - WithWildCardIndexOnEntity value; + WithWildCardIndexHavingProjectionOnEntity value; } diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index a74594bff0..74458b9971 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -6,6 +6,7 @@ * Extended support for <> entities. * Include/exclude `null` properties on write to `Document` through `@Field(write=…)`. +* Support for <>. [[new-features.3.2]] == What's New in Spring Data MongoDB 3.2 diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 7caf1093b9..e301826697 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -782,9 +782,9 @@ db.user.createIndex({ "userMetadata.$**" : 1 }, {}) ---- ==== -The `@WildcardIndex` annotation allows a declarative index setup an can be added on either a type or property. +The `@WildcardIndex` annotation allows a declarative index setup that can used either with a document type or property. -If placed on a type that is a root level domain entity (one having an `@Document` annotation) will advise the index creator to create a +If placed on a type that is a root level domain entity (one annotated with `@Document`) , the index resolver will create a wildcard index for it. .Wildcard index on domain type @@ -794,7 +794,7 @@ wildcard index for it. @Document @WildcardIndexed public class Product { - ... + // … } ---- [source,javascript] @@ -828,7 +828,8 @@ db.user.createIndex( ==== Wildcard indexes can also be expressed by adding the annotation directly to the field. -Please note that `wildcardProjection` is not allowed on nested paths. +Please note that `wildcardProjection` is not allowed on nested paths such as properties. +Projections on types annotated with `@WildcardIndexed` are omitted during index creation. .Wildcard index on property ==== From 23177fef0c0fe163e44d42543f17a621969d6e5f Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 12 Jul 2021 10:32:13 +0200 Subject: [PATCH 0463/1381] Custom Converter should also be applicable for simple types. This commit fixes a regression that prevented custom converters from being applied to types considered store native ones. Original pull request: #3703. Fixes #3670 --- .../core/convert/MappingMongoConverter.java | 6 ++++- .../MappingMongoConverterUnitTests.java | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) 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 aced009cda..83be993b93 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 @@ -1173,7 +1173,7 @@ protected Object getPotentiallyConvertedSimpleRead(Object value, TypeInformation @SuppressWarnings({ "rawtypes", "unchecked" }) private Object getPotentiallyConvertedSimpleRead(Object value, @Nullable Class target) { - if (target == null || ClassUtils.isAssignableValue(target, value)) { + if (target == null) { return value; } @@ -1181,6 +1181,10 @@ private Object getPotentiallyConvertedSimpleRead(Object value, @Nullable Class) target, value.toString()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 369f6dbdef..759be5c6b3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -30,6 +30,7 @@ import java.time.temporal.ChronoUnit; import java.util.*; +import org.bson.types.Binary; import org.bson.types.Code; import org.bson.types.Decimal128; import org.bson.types.ObjectId; @@ -2568,6 +2569,21 @@ void readsMapContainingNullValue() { .containsEntry("item3", "i3"); } + @Test // GH-3670 + void appliesCustomConverterEvenToSimpleTypes() { + + converter = new MappingMongoConverter(resolver, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(it -> { + it.registerConverter(new MongoSimpleTypeConverter()); + })); + converter.afterPropertiesSet(); + + org.bson.Document source = new org.bson.Document("content", new Binary(new byte[] {0x00, 0x42})); + + GenericType target = converter.read(GenericType.class, source); + assertThat(target.content).isInstanceOf(byte[].class); + } + static class GenericType { T content; } @@ -3136,6 +3152,15 @@ public TypeImplementingMap convert(org.bson.Document source) { } } + @ReadingConverter + public static class MongoSimpleTypeConverter implements Converter { + + @Override + public byte[] convert(Binary source) { + return source.getData(); + } + } + static class TypeWrappingTypeImplementingMap { String id; From 3f27e8e152768d0ecff078190720ff59acdb7a70 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 12 Jul 2021 07:56:59 +0200 Subject: [PATCH 0464/1381] Fix raw document conversion in Collection like properties. Along the lines make sure to convert map like structures correctly if they do not come as a Document, eg. cause they got converted to a plain Map in a post load, pre convert event. Closes #3702 Original pull request: #3704. --- .../core/convert/MappingMongoConverter.java | 14 ++++++- .../MappingMongoConverterUnitTests.java | 39 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) 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 83be993b93..9cb1f89797 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 @@ -2040,7 +2040,19 @@ public S convert(Object source, TypeInformation } if (typeHint.isMap()) { - return (S) mapConverter.convert(this, (Bson) source, typeHint); + + if(ClassUtils.isAssignable(Document.class, typeHint.getType())) { + return (S) documentConverter.convert(this, (Bson) source, typeHint); + } + + if(source instanceof Bson) { + return (S) mapConverter.convert(this, (Bson) source, typeHint); + } + if(source instanceof Map) { + return (S) mapConverter.convert(this, new Document((Map) source), typeHint); + } + + throw new IllegalArgumentException(String.format("Expected map like structure but found %s", source.getClass())); } if (source instanceof DBRef) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 759be5c6b3..dbc9e3d752 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -2584,6 +2584,38 @@ void appliesCustomConverterEvenToSimpleTypes() { assertThat(target.content).isInstanceOf(byte[].class); } + @Test // GH-3702 + void readsRawDocument() { + + org.bson.Document source = new org.bson.Document("_id", "id-1").append("raw", new org.bson.Document("simple", 1).append("document", new org.bson.Document("inner-doc", 1))); + + WithRawDocumentProperties target = converter.read(WithRawDocumentProperties.class, source); + + assertThat(target.raw).isInstanceOf(org.bson.Document.class).isEqualTo( new org.bson.Document("simple", 1).append("document", new org.bson.Document("inner-doc", 1))); + } + + @Test // GH-3702 + void readsListOfRawDocument() { + + org.bson.Document source = new org.bson.Document("_id", "id-1").append("listOfRaw", Arrays.asList(new org.bson.Document("simple", 1).append("document", new org.bson.Document("inner-doc", 1)))); + + WithRawDocumentProperties target = converter.read(WithRawDocumentProperties.class, source); + + assertThat(target.listOfRaw) + .containsExactly(new org.bson.Document("simple", 1).append("document", new org.bson.Document("inner-doc", 1))); + } + + @Test // GH-3692 + void readsMapThatDoesNotComeAsDocument() { + + org.bson.Document source = new org.bson.Document("_id", "id-1").append("mapOfObjects", Collections.singletonMap("simple", 1)); + + ClassWithMapProperty target = converter.read(ClassWithMapProperty.class, source); + + assertThat(target.mapOfObjects).containsEntry("simple",1); + + } + static class GenericType { T content; } @@ -3243,6 +3275,13 @@ public Set> entrySet() { } } + static class WithRawDocumentProperties { + + String id; + org.bson.Document raw; + List listOfRaw; + } + static class WithFieldWrite { @org.springframework.data.mongodb.core.mapping.Field( From f38f6d67ab54b29454203946d55e2004dc26504d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 15 Jul 2021 09:59:46 +0200 Subject: [PATCH 0465/1381] Polishing. Support DBObject and Map that as source for entity materialization and map conversion. See #3702 Original pull request: #3704. --- .../core/convert/MappingMongoConverter.java | 13 +++--- .../data/mongodb/util/BsonUtils.java | 43 +++++++++++++++++++ .../MappingMongoConverterUnitTests.java | 5 ++- .../data/mongodb/util/json/BsonUtilsTest.java | 17 +++++++- 4 files changed, 67 insertions(+), 11 deletions(-) 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 9cb1f89797..48505559c0 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 @@ -2042,14 +2042,11 @@ public S convert(Object source, TypeInformation if (typeHint.isMap()) { if(ClassUtils.isAssignable(Document.class, typeHint.getType())) { - return (S) documentConverter.convert(this, (Bson) source, typeHint); + return (S) documentConverter.convert(this, BsonUtils.asBson(source), typeHint); } - if(source instanceof Bson) { - return (S) mapConverter.convert(this, (Bson) source, typeHint); - } - if(source instanceof Map) { - return (S) mapConverter.convert(this, new Document((Map) source), typeHint); + if (BsonUtils.supportsBson(source)) { + return (S) mapConverter.convert(this, BsonUtils.asBson(source), typeHint); } throw new IllegalArgumentException(String.format("Expected map like structure but found %s", source.getClass())); @@ -2064,8 +2061,8 @@ public S convert(Object source, TypeInformation String.format(INCOMPATIBLE_TYPES, source, BasicDBList.class, typeHint.getType(), getPath())); } - if (source instanceof Bson) { - return (S) documentConverter.convert(this, (Bson) source, typeHint); + if (BsonUtils.supportsBson(source)) { + return (S) documentConverter.convert(this, BsonUtils.asBson(source), typeHint); } return (S) elementConverter.convert(source, typeHint); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index 4d51af7dee..d452ad662f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -494,6 +494,49 @@ private static Map getAsMap(Object source) { return null; } + /** + * Returns the given source object as {@link Bson}, i.e. {@link Document}s and maps as is or throw + * {@link IllegalArgumentException}. + * + * @param source + * @return the converted/casted source object. + * @throws IllegalArgumentException if {@code source} cannot be converted/cast to {@link Bson}. + * @since 3.2.3 + * @see #supportsBson(Object) + */ + @SuppressWarnings("unchecked") + public static Bson asBson(Object source) { + + if (source instanceof Document) { + return (Document) source; + } + + if (source instanceof BasicDBObject) { + return (BasicDBObject) source; + } + + if (source instanceof DBObject) { + return new Document(((DBObject) source).toMap()); + } + + if (source instanceof Map) { + return new Document((Map) source); + } + + throw new IllegalArgumentException(String.format("Cannot convert %s to Bson", source)); + } + + /** + * Returns the given source can be used/converted as {@link Bson}. + * + * @param source + * @return {@literal true} if the given source can be converted to {@link Bson}. + * @since 3.2.3 + */ + public static boolean supportsBson(Object source) { + return source instanceof DBObject || source instanceof Map; + } + /** * Returns given object as {@link Collection}. Will return the {@link Collection} as is if the source is a * {@link Collection} already, will convert an array into a {@link Collection} or simply create a single element diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index dbc9e3d752..ca94ac6e3c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -934,10 +934,11 @@ void convertsSetToBasicDBList() { assertThat(readResult.iterator().next()).isInstanceOf(Address.class); } - @Test // DATAMONGO-402 + @Test // DATAMONGO-402, GH-3702 void readsMemberClassCorrectly() { - org.bson.Document document = new org.bson.Document("inner", new org.bson.Document("value", "FOO!")); + org.bson.Document document = new org.bson.Document("inner", + new LinkedHashMap<>(new org.bson.Document("value", "FOO!"))); Outer outer = converter.read(Outer.class, document); assertThat(outer.inner).isNotNull(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java index 8210dd9a6f..166932c237 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/BsonUtilsTest.java @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.List; +import java.util.Collections; import org.bson.BsonDouble; import org.bson.BsonInt32; @@ -29,10 +29,16 @@ import org.bson.Document; import org.bson.types.ObjectId; import org.junit.jupiter.api.Test; + import org.springframework.data.mongodb.util.BsonUtils; +import com.mongodb.BasicDBList; + /** + * Unit tests for {@link BsonUtils}. + * * @author Christoph Strobl + * @author Mark Paluch */ class BsonUtilsTest { @@ -111,4 +117,13 @@ void asCollectionConvertsWrapsNonIterable() { assertThat((Collection)BsonUtils.asCollection(source)).containsExactly(source); } + + @Test // GH-3702 + void supportsBsonShouldReportIfConversionSupported() { + + assertThat(BsonUtils.supportsBson("foo")).isFalse(); + assertThat(BsonUtils.supportsBson(new Document())).isTrue(); + assertThat(BsonUtils.supportsBson(new BasicDBList())).isTrue(); + assertThat(BsonUtils.supportsBson(Collections.emptyMap())).isTrue(); + } } From bacbd7133e6d9e0f2969261110ad16ebfa0ff98a Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 15 Jul 2021 09:52:50 +0200 Subject: [PATCH 0466/1381] Add support for creating Time Series collection. Introduce time series to CollectionOptions and add dedicated TimeSeries annotation to derive values from. Closes #3731 Original pull request: #3732. --- .../data/mongodb/core/CollectionOptions.java | 144 ++++++++++++++++-- .../data/mongodb/core/EntityOperations.java | 72 +++++++++ .../data/mongodb/core/MongoTemplate.java | 28 +++- .../mongodb/core/ReactiveMongoTemplate.java | 17 ++- .../data/mongodb/core/mapping/TimeSeries.java | 86 +++++++++++ .../core/timeseries/Granularities.java | 45 ++++++ .../mongodb/core/timeseries/Granularity.java | 27 ++++ .../mongodb/core/MongoTemplateUnitTests.java | 54 +++++-- .../core/ReactiveMongoTemplateUnitTests.java | 47 ++++++ src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/reference/mongodb.adoc | 1 + src/main/asciidoc/reference/time-series.adoc | 45 ++++++ 12 files changed, 547 insertions(+), 20 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java create mode 100644 src/main/asciidoc/reference/time-series.adoc 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 ca61d18d96..3e509e54f2 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 @@ -17,8 +17,11 @@ import java.util.Optional; +import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; +import org.springframework.data.mongodb.core.timeseries.Granularities; +import org.springframework.data.mongodb.core.timeseries.Granularity; import org.springframework.data.mongodb.core.validation.Validator; import org.springframework.data.util.Optionals; import org.springframework.lang.Nullable; @@ -42,6 +45,7 @@ public class CollectionOptions { private @Nullable Boolean capped; private @Nullable Collation collation; private ValidationOptions validationOptions; + private @Nullable TimeSeriesOptions timeSeriesOptions; /** * Constructs a new CollectionOptions instance. @@ -54,17 +58,19 @@ public class CollectionOptions { */ @Deprecated public CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped) { - this(size, maxDocuments, capped, null, ValidationOptions.none()); + this(size, maxDocuments, capped, null, ValidationOptions.none(), null); } private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped, - @Nullable Collation collation, ValidationOptions validationOptions) { + @Nullable Collation collation, ValidationOptions validationOptions, + @Nullable TimeSeriesOptions timeSeriesOptions) { this.maxDocuments = maxDocuments; this.size = size; this.capped = capped; this.collation = collation; this.validationOptions = validationOptions; + this.timeSeriesOptions = timeSeriesOptions; } /** @@ -78,7 +84,7 @@ public static CollectionOptions just(Collation collation) { Assert.notNull(collation, "Collation must not be null!"); - return new CollectionOptions(null, null, null, collation, ValidationOptions.none()); + return new CollectionOptions(null, null, null, collation, ValidationOptions.none(), null); } /** @@ -88,7 +94,21 @@ public static CollectionOptions just(Collation collation) { * @since 2.0 */ public static CollectionOptions empty() { - return new CollectionOptions(null, null, null, null, ValidationOptions.none()); + return new CollectionOptions(null, null, null, null, ValidationOptions.none(), null); + } + + /** + * Quick way to set up {@link CollectionOptions} for a Time Series collection. For more advanced settings use + * {@link #timeSeries(TimeSeriesOptions)}. + * + * @param timeField The name of the property which contains the date in each time series document. Must not be + * {@literal null}. + * @return new instance of {@link CollectionOptions}. + * @see #timeSeries(TimeSeriesOptions) + * @since 3.3 + */ + public static CollectionOptions timeSeries(String timeField) { + return empty().timeSeries(TimeSeriesOptions.timeSeries(timeField)); } /** @@ -99,7 +119,7 @@ public static CollectionOptions empty() { * @since 2.0 */ public CollectionOptions capped() { - return new CollectionOptions(size, maxDocuments, true, collation, validationOptions); + return new CollectionOptions(size, maxDocuments, true, collation, validationOptions, null); } /** @@ -110,7 +130,7 @@ public CollectionOptions capped() { * @since 2.0 */ public CollectionOptions maxDocuments(long maxDocuments) { - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions); } /** @@ -121,7 +141,7 @@ public CollectionOptions maxDocuments(long maxDocuments) { * @since 2.0 */ public CollectionOptions size(long size) { - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions); } /** @@ -132,7 +152,7 @@ public CollectionOptions size(long size) { * @since 2.0 */ public CollectionOptions collation(@Nullable Collation collation) { - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions); } /** @@ -252,7 +272,20 @@ public CollectionOptions schemaValidationAction(ValidationAction validationActio public CollectionOptions validation(ValidationOptions validationOptions) { Assert.notNull(validationOptions, "ValidationOptions must not be null!"); - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions); + } + + /** + * Create new {@link CollectionOptions} with the given {@link TimeSeriesOptions}. + * + * @param timeSeriesOptions must not be {@literal null}. + * @return new instance of {@link CollectionOptions}. + * @since 3.3 + */ + public CollectionOptions timeSeries(TimeSeriesOptions timeSeriesOptions) { + + Assert.notNull(timeSeriesOptions, "TimeSeriesOptions must not be null!"); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions); } /** @@ -303,6 +336,16 @@ public Optional getValidationOptions() { return validationOptions.isEmpty() ? Optional.empty() : Optional.of(validationOptions); } + /** + * Get the {@link TimeSeriesOptions} if available. + * + * @return {@link Optional#empty()} if not specified. + * @since 3.3 + */ + public Optional getTimeSeriesOptions() { + return Optional.ofNullable(timeSeriesOptions); + } + /** * Encapsulation of ValidationOptions options. * @@ -398,4 +441,87 @@ boolean isEmpty() { return !Optionals.isAnyPresent(getValidator(), getValidationAction(), getValidationLevel()); } } + + /** + * Options applicable to Time Series collections. + * + * @author Christoph Strobl + * @since 3.3 + * @see https://docs.mongodb.com/manual/core/timeseries-collections + */ + public static class TimeSeriesOptions { + + private final String timeField; + + @Nullable // + private String metaField; + + private Granularity granularity; + + private TimeSeriesOptions(String timeField, @Nullable String metaField, Granularity granularity) { + + this.timeField = timeField; + this.metaField = metaField; + this.granularity = granularity; + } + + /** + * Create a new instance of {@link TimeSeriesOptions} using the given field as its {@literal timeField}. The one, + * that contains the date in each time series document.
      + * {@link Field#name() Annotated fieldnames} will be considered during the mapping process. + * + * @param timeField must not be {@literal null}. + * @return new instance of {@link TimeSeriesOptions}. + */ + public static TimeSeriesOptions timeSeries(String timeField) { + return new TimeSeriesOptions(timeField, null, Granularities.DEFAULT); + } + + /** + * Set the name of the field which contains metadata in each time series document. Should not be the {@literal id} + * nor {@link TimeSeriesOptions#timeSeries(String)} timeField} nor point to an {@literal array} or + * {@link java.util.Collection}.
      + * {@link Field#name() Annotated fieldnames} will be considered during the mapping process. + * + * @param metaField must not be {@literal null}. + * @return new instance of {@link TimeSeriesOptions}. + */ + public TimeSeriesOptions metaField(String metaField) { + return new TimeSeriesOptions(timeField, metaField, granularity); + } + + /** + * Select the {@link Granularity} parameter to define how data in the time series collection is organized. Select + * one that is closest to the time span between incoming measurements. + * + * @return new instance of {@link TimeSeriesOptions}. + */ + public TimeSeriesOptions granularity(Granularity granularity) { + return new TimeSeriesOptions(timeField, metaField, granularity); + } + + /** + * @return never {@literal null}. + */ + public String getTimeField() { + return timeField; + } + + /** + * @return can be {@literal null}. Might be an {@literal empty} {@link String} as well, so maybe check via + * {@link org.springframework.util.StringUtils#hasText(String)}. + */ + @Nullable + public String getMetaField() { + return metaField; + } + + /** + * @return never {@literal null}. + */ + public Granularity getGranularity() { + return granularity; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index f2daf0287d..9fb8836e1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -29,19 +29,23 @@ import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.ConvertingPropertyAccessor; +import org.springframework.data.mongodb.core.CollectionOptions.TimeSeriesOptions; import org.springframework.data.mongodb.core.convert.MongoWriter; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; +import org.springframework.data.mongodb.core.mapping.TimeSeries; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.timeseries.Granularities; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; /** * Common operations performed on an entity in the context of it's mapping metadata. @@ -778,6 +782,24 @@ interface TypedOperations { * @return */ Optional getCollation(Query query); + + /** + * Derive the applicable {@link CollectionOptions} for the given type. + * + * @return never {@literal null}. + * @since 3.3 + */ + CollectionOptions getCollectionOptions(); + + /** + * Map the fields of a given {@link TimeSeriesOptions} against the target domain type to consider potentially + * annotated field names. + * + * @param options must not be {@literal null}. + * @return never {@literal null}. + * @since 3.3 + */ + TimeSeriesOptions mapTimeSeriesOptions(TimeSeriesOptions options); } /** @@ -817,6 +839,16 @@ public Optional getCollation(Query query) { return query.getCollation(); } + + @Override + public CollectionOptions getCollectionOptions() { + return CollectionOptions.empty(); + } + + @Override + public TimeSeriesOptions mapTimeSeriesOptions(TimeSeriesOptions options) { + return options; + } } /** @@ -854,6 +886,46 @@ public Optional getCollation(Query query) { return Optional.ofNullable(entity.getCollation()); } + + @Override + public CollectionOptions getCollectionOptions() { + + CollectionOptions collectionOptions = CollectionOptions.empty(); + if (entity.hasCollation()) { + collectionOptions = collectionOptions.collation(entity.getCollation()); + } + + if (entity.isAnnotationPresent(TimeSeries.class)) { + + TimeSeries timeSeries = entity.getRequiredAnnotation(TimeSeries.class); + TimeSeriesOptions options = TimeSeriesOptions.timeSeries(timeSeries.timeField()); + if (StringUtils.hasText(timeSeries.metaField())) { + options = options.metaField(timeSeries.metaField()); + } + if (!Granularities.DEFAULT.equals(timeSeries.granularity())) { + options = options.granularity(timeSeries.granularity()); + } + collectionOptions = collectionOptions.timeSeries(options); + } + + return collectionOptions; + } + + @Override + public TimeSeriesOptions mapTimeSeriesOptions(TimeSeriesOptions source) { + + TimeSeriesOptions target = TimeSeriesOptions.timeSeries(mappedNameOrDefault(source.getTimeField())); + + if (StringUtils.hasText(source.getMetaField())) { + target = target.metaField(mappedNameOrDefault(source.getMetaField())); + } + return target.granularity(source.getGranularity()); + } + + private String mappedNameOrDefault(String name) { + MongoPersistentProperty persistentProperty = entity.getPersistentProperty(name); + return persistentProperty != null ? persistentProperty.getFieldName() : name; + } } } 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 eae4f42706..c833e511bf 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 @@ -99,6 +99,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; +import org.springframework.data.mongodb.core.timeseries.Granularities; import org.springframework.data.mongodb.core.validation.Validator; import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; @@ -597,7 +598,7 @@ public void setSessionSynchronization(SessionSynchronization sessionSynchronizat * @see org.springframework.data.mongodb.core.MongoOperations#createCollection(java.lang.Class) */ public MongoCollection createCollection(Class entityClass) { - return createCollection(entityClass, CollectionOptions.empty()); + return createCollection(entityClass, operations.forType(entityClass).getCollectionOptions()); } /* @@ -2435,6 +2436,19 @@ protected MongoCollection doCreateCollection(String collectionName, Do co.validationOptions(options); } + if(collectionOptions.containsKey("timeseries")) { + + Document timeSeries = collectionOptions.get("timeseries", Document.class); + com.mongodb.client.model.TimeSeriesOptions options = new com.mongodb.client.model.TimeSeriesOptions(timeSeries.getString("timeField")); + if(timeSeries.containsKey("metaField")) { + options.metaField(timeSeries.getString("metaField")); + } + if(timeSeries.containsKey("granularity")) { + options.granularity(TimeSeriesGranularity.valueOf(timeSeries.getString("granularity").toUpperCase())); + } + co.timeSeriesOptions(options); + } + db.createCollection(collectionName, co); MongoCollection coll = db.getCollection(collectionName, Document.class); @@ -2589,6 +2603,18 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio collectionOptions.getValidationOptions().ifPresent(it -> it.getValidator() // .ifPresent(val -> doc.put("validator", getMappedValidator(val, targetType)))); + + collectionOptions.getTimeSeriesOptions().map(operations.forType(targetType)::mapTimeSeriesOptions).ifPresent(it -> { + + Document timeseries = new Document("timeField", it.getTimeField()); + if(StringUtils.hasText(it.getMetaField())) { + timeseries.append("metaField", it.getMetaField()); + } + if(!Granularities.DEFAULT.equals(it.getGranularity())) { + timeseries.append("granularity", it.getGranularity().name().toLowerCase()); + } + doc.put("timeseries", timeseries); + }); } return doc; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 614894f3b6..2403e9a394 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,6 +17,7 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import org.springframework.data.mongodb.core.timeseries.Granularities; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -665,7 +666,7 @@ public Mono createMono(String collectionName, ReactiveCollectionCallback< * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#createCollection(java.lang.Class) */ public Mono> createCollection(Class entityClass) { - return createCollection(entityClass, CollectionOptions.empty()); + return createCollection(entityClass, operations.forType(entityClass).getCollectionOptions()); } /* @@ -2505,6 +2506,20 @@ protected CreateCollectionOptions convertToCreateCollectionOptions(@Nullable Col result.validationOptions(validationOptions); }); + collectionOptions.getTimeSeriesOptions().map(operations.forType(entityType)::mapTimeSeriesOptions).ifPresent(it -> { + + TimeSeriesOptions options = new TimeSeriesOptions(it.getTimeField()); + + if(StringUtils.hasText(it.getMetaField())) { + options.metaField(it.getMetaField()); + } + if(!Granularities.DEFAULT.equals(it.getGranularity())) { + options.granularity(TimeSeriesGranularity.valueOf(it.getGranularity().name().toUpperCase())); + } + + result.timeSeriesOptions(options); + }); + return result; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java new file mode 100644 index 0000000000..8a5fe255e0 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java @@ -0,0 +1,86 @@ +/* + * Copyright 2021 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 + * + * https://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.mapping; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.data.mongodb.core.timeseries.Granularities; + +/** + * Identifies a domain object to be persisted to a MongoDB Time Series collection. + * + * @author Christoph Strobl + * @since 3.3 + * @see https://docs.mongodb.com/manual/core/timeseries-collections + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +@Document +public @interface TimeSeries { + + /** + * The collection the document representing the entity is supposed to be stored in. If not configured, a default + * collection name will be derived from the type's name. The attribute supports SpEL expressions to dynamically + * calculate the collection based on a per operation basis. + * + * @return the name of the collection to be used. + * @see Document#collection() + */ + @AliasFor(annotation = Document.class, attribute = "collection") + String collection() default ""; + + /** + * The name of the property which contains the date in each time series document.
      + * {@link Field#name() Annotated fieldnames} will be considered during the mapping process. + * + * @return never {@literal null}. + */ + String timeField(); + + /** + * The name of the field which contains metadata in each time series document. Should not be the {@literal id} nor + * {@link #timeField()} nor point to an {@literal array} or {@link java.util.Collection}.
      + * {@link Field#name() Annotated fieldnames} will be considered during the mapping process. + * + * @return empty {@link String} by default. + */ + String metaField() default ""; + + /** + * Select the {@link Granularities granularity} parameter to define how data in the time series collection is + * organized. + * + * @return {@link Granularities#DEFAULT server default} by default. + */ + Granularities granularity() default Granularities.DEFAULT; + + /** + * Defines the collation to apply when executing a query or creating indexes. + * + * @return an empty {@link String} by default. + * @see Document#collation() + */ + @AliasFor(annotation = Document.class, attribute = "collation") + String collation() default ""; + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java new file mode 100644 index 0000000000..f4cac5232c --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java @@ -0,0 +1,45 @@ +/* + * Copyright 2021 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 + * + * https://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.timeseries; + +/** + * {@link Granularity Granularities} available for Time Series data. + * + * @author Christoph Strobl + * @since 3.3 + */ +public enum Granularities implements Granularity { + + /** + * Server default value to indicate no explicit value should be sent. + */ + DEFAULT, + + /** + * High frequency ingestion. + */ + SECONDS, + + /** + * Medium frequency ingestion. + */ + MINUTES, + + /** + * Low frequency ingestion. + */ + HOURS +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java new file mode 100644 index 0000000000..c8fe496adb --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 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 + * + * https://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.timeseries; + +/** + * The Granularity of time series data that is closest to the time span between incoming measurements. + * + * @author Christoph Strobl + * @since 3.3 + */ +public interface Granularity { + + String name(); +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 68c83a2757..cc215c956c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -19,12 +19,14 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.*; +import com.mongodb.client.model.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.math.BigInteger; import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -82,6 +84,7 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.Sharded; +import org.springframework.data.mongodb.core.mapping.TimeSeries; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterConvertCallback; import org.springframework.data.mongodb.core.mapping.event.AfterSaveCallback; @@ -98,6 +101,7 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.core.timeseries.Granularities; import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; @@ -117,15 +121,6 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.CountOptions; -import com.mongodb.client.model.CreateCollectionOptions; -import com.mongodb.client.model.DeleteOptions; -import com.mongodb.client.model.FindOneAndDeleteOptions; -import com.mongodb.client.model.FindOneAndReplaceOptions; -import com.mongodb.client.model.FindOneAndUpdateOptions; -import com.mongodb.client.model.MapReduceAction; -import com.mongodb.client.model.ReplaceOptions; -import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; @@ -2256,6 +2251,30 @@ void saveErrorsOnCollectionLikeObjects() { .isThrownBy(() -> template.save(new ArrayList<>(Arrays.asList(1, 2, 3)), "myList")); } + @Test // GH-3731 + void createCollectionShouldSetUpTimeSeriesWithDefaults() { + + template.createCollection(TimeSeriesTypeWithDefaults.class); + + ArgumentCaptor options = ArgumentCaptor.forClass(CreateCollectionOptions.class); + verify(db).createCollection(any(), options.capture()); + + assertThat(options.getValue().getTimeSeriesOptions().toString()) + .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("timestamp").toString()); + } + + @Test // GH-3731 + void createCollectionShouldSetUpTimeSeries() { + + template.createCollection(TimeSeriesType.class); + + ArgumentCaptor options = ArgumentCaptor.forClass(CreateCollectionOptions.class); + verify(db).createCollection(any(), options.capture()); + + assertThat(options.getValue().getTimeSeriesOptions().toString()) + .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").metaField("meta").granularity(TimeSeriesGranularity.HOURS).toString()); + } + class AutogenerateableId { @Id BigInteger id; @@ -2358,6 +2377,23 @@ static class WithShardKeyPointingToNested { WithNamedFields nested; } + @TimeSeries(timeField = "timestamp") + static class TimeSeriesTypeWithDefaults { + + String id; + Instant timestamp; + } + + @TimeSeries(timeField = "timestamp", metaField = "meta", granularity = Granularities.HOURS) + static class TimeSeriesType { + + String id; + + @Field("time_stamp") + Instant timestamp; + Object meta; + } + static class TypeImplementingIterator implements Iterator { @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 5c5a307f1d..17fde7ec32 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -20,15 +20,21 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.assertThat; +import com.mongodb.client.model.TimeSeriesGranularity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplateUnitTests.TimeSeriesType; +import org.springframework.data.mongodb.core.MongoTemplateUnitTests.TimeSeriesTypeWithDefaults; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.mapping.TimeSeries; +import org.springframework.data.mongodb.core.timeseries.Granularities; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -1426,6 +1432,30 @@ void insertErrorsOnPublisher() { .isThrownBy(() -> template.insert(publisher)); } + @Test // GH-3731 + void createCollectionShouldSetUpTimeSeriesWithDefaults() { + + template.createCollection(TimeSeriesTypeWithDefaults.class).subscribe(); + + ArgumentCaptor options = ArgumentCaptor.forClass(CreateCollectionOptions.class); + verify(db).createCollection(any(), options.capture()); + + assertThat(options.getValue().getTimeSeriesOptions().toString()) + .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("timestamp").toString()); + } + + @Test // GH-3731 + void createCollectionShouldSetUpTimeSeries() { + + template.createCollection(TimeSeriesType.class).subscribe(); + + ArgumentCaptor options = ArgumentCaptor.forClass(CreateCollectionOptions.class); + verify(db).createCollection(any(), options.capture()); + + assertThat(options.getValue().getTimeSeriesOptions().toString()) + .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").metaField("meta").granularity(TimeSeriesGranularity.HOURS).toString()); + } + private void stubFindSubscribe(Document document) { Publisher realPublisher = Flux.just(document); @@ -1483,6 +1513,23 @@ static class EntityWithListOfSimple { List grades; } + @TimeSeries(timeField = "timestamp") + static class TimeSeriesTypeWithDefaults { + + String id; + Instant timestamp; + } + + @TimeSeries(timeField = "timestamp", metaField = "meta", granularity = Granularities.HOURS) + static class TimeSeriesType { + + String id; + + @Field("time_stamp") + Instant timestamp; + Object meta; + } + static class ValueCapturingEntityCallback { private final List values = new ArrayList<>(1); diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 74458b9971..ddfa1e96ec 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -5,6 +5,7 @@ == What's New in Spring Data MongoDB 3.3 * Extended support for <> entities. +* Support for <> collections. * Include/exclude `null` properties on write to `Document` through `@Field(write=…)`. * Support for <>. diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index fb35bb655b..84afc7ea09 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -3382,3 +3382,4 @@ class GridFsClient { include::tailable-cursors.adoc[] include::change-streams.adoc[] +include::time-series.adoc[] diff --git a/src/main/asciidoc/reference/time-series.adoc b/src/main/asciidoc/reference/time-series.adoc new file mode 100644 index 0000000000..ac36e4026e --- /dev/null +++ b/src/main/asciidoc/reference/time-series.adoc @@ -0,0 +1,45 @@ +[[time-series]] +== Time Series + +MongoDB 5.0 introduced https://docs.mongodb.com/manual/core/timeseries-collections/[Time Series] collections optimized to efficiently store sequences of measurements. +Those collections need to be actively created before inserting any data. This can be done by manually executing the command, defining time series collection options or extracting options from a `@TimeSeries` annotation as shown in the examples below. + +.Create a Time Series Collection +==== +.Create a Time Series via the MongoDB Driver +[code, java] +---- +template.execute(db -> { + + com.mongodb.client.model.CreateCollectionOptions options = new CreateCollectionOptions(); + options.timeSeriesOptions(new TimeSeriesOptions("timestamp")); + + db.createCollection("weather", options); + return "OK"; +}); +---- + +.Create a Time Series Collection with CollectionOptions +[code, java] +---- +template.createCollection("weather", CollectionOptions.timeSeries("timestamp")); +---- + +.Create a Time Series Collection derived from an Annotation +[code, java] +---- +@TimeSeries(collection="weather", timeField = "timestamp") +public class Measurement { + + String id; + Instant timestamp; + // ... +} + +template.createCollection(Measurement.class); +---- +==== + +The snippets above can easily be transferred to the reactive API offering the very same methods. +Just make sure to _subscribe_. + From f00991dc293dceee172b1ece6613dde599a0665d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 16 Jul 2021 09:41:16 +0200 Subject: [PATCH 0467/1381] Polishing. Rename Granularities/Granularity to Granularity and GranularityDefinition to proivide a more natural wording towards using predefined granularities. Validate presence of referenced properties through the TimeSeries annotation. Tweak Javadoc, reformat code, add unit tests. See #3731 Original pull request: #3732. --- .../data/mongodb/core/CollectionOptions.java | 24 ++++---- .../data/mongodb/core/EntityOperations.java | 16 ++++- .../data/mongodb/core/MongoTemplate.java | 58 +++++++++--------- .../mongodb/core/ReactiveMongoTemplate.java | 22 +++---- .../data/mongodb/core/mapping/TimeSeries.java | 17 +++--- .../mongodb/core/timeseries/Granularity.java | 24 +++++++- ...rities.java => GranularityDefinition.java} | 24 +------- .../core/EntityOperationsUnitTests.java | 60 +++++++++++++++++++ .../mongodb/core/MongoTemplateUnitTests.java | 26 +++++--- .../core/ReactiveMongoTemplateUnitTests.java | 24 ++++---- src/main/asciidoc/reference/time-series.adoc | 15 ++--- 11 files changed, 198 insertions(+), 112 deletions(-) rename spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/{Granularities.java => GranularityDefinition.java} (66%) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java 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 3e509e54f2..edff52bb74 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 @@ -20,8 +20,8 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; -import org.springframework.data.mongodb.core.timeseries.Granularities; import org.springframework.data.mongodb.core.timeseries.Granularity; +import org.springframework.data.mongodb.core.timeseries.GranularityDefinition; import org.springframework.data.mongodb.core.validation.Validator; import org.springframework.data.util.Optionals; import org.springframework.lang.Nullable; @@ -100,7 +100,7 @@ public static CollectionOptions empty() { /** * Quick way to set up {@link CollectionOptions} for a Time Series collection. For more advanced settings use * {@link #timeSeries(TimeSeriesOptions)}. - * + * * @param timeField The name of the property which contains the date in each time series document. Must not be * {@literal null}. * @return new instance of {@link CollectionOptions}. @@ -454,12 +454,13 @@ public static class TimeSeriesOptions { private final String timeField; - @Nullable // - private String metaField; + private @Nullable final String metaField; + + private final GranularityDefinition granularity; - private Granularity granularity; + private TimeSeriesOptions(String timeField, @Nullable String metaField, GranularityDefinition granularity) { - private TimeSeriesOptions(String timeField, @Nullable String metaField, Granularity granularity) { + Assert.hasText(timeField, "Time field must not be empty or null!"); this.timeField = timeField; this.metaField = metaField; @@ -475,7 +476,7 @@ private TimeSeriesOptions(String timeField, @Nullable String metaField, Granular * @return new instance of {@link TimeSeriesOptions}. */ public static TimeSeriesOptions timeSeries(String timeField) { - return new TimeSeriesOptions(timeField, null, Granularities.DEFAULT); + return new TimeSeriesOptions(timeField, null, Granularity.DEFAULT); } /** @@ -492,12 +493,13 @@ public TimeSeriesOptions metaField(String metaField) { } /** - * Select the {@link Granularity} parameter to define how data in the time series collection is organized. Select - * one that is closest to the time span between incoming measurements. + * Select the {@link GranularityDefinition} parameter to define how data in the time series collection is organized. + * Select one that is closest to the time span between incoming measurements. * * @return new instance of {@link TimeSeriesOptions}. + * @see Granularity */ - public TimeSeriesOptions granularity(Granularity granularity) { + public TimeSeriesOptions granularity(GranularityDefinition granularity) { return new TimeSeriesOptions(timeField, metaField, granularity); } @@ -520,7 +522,7 @@ public String getMetaField() { /** * @return never {@literal null}. */ - public Granularity getGranularity() { + public GranularityDefinition getGranularity() { return granularity; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index 9fb8836e1a..3bba17aaef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -38,7 +38,7 @@ import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.core.timeseries.Granularities; +import org.springframework.data.mongodb.core.timeseries.Granularity; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -898,11 +898,23 @@ public CollectionOptions getCollectionOptions() { if (entity.isAnnotationPresent(TimeSeries.class)) { TimeSeries timeSeries = entity.getRequiredAnnotation(TimeSeries.class); + + if (entity.getPersistentProperty(timeSeries.timeField()) == null) { + throw new MappingException(String.format("Time series field '%s' does not exist in type %s", + timeSeries.timeField(), entity.getName())); + } + TimeSeriesOptions options = TimeSeriesOptions.timeSeries(timeSeries.timeField()); if (StringUtils.hasText(timeSeries.metaField())) { + + if (entity.getPersistentProperty(timeSeries.metaField()) == null) { + throw new MappingException( + String.format("Meta field '%s' does not exist in type %s", timeSeries.metaField(), entity.getName())); + } + options = options.metaField(timeSeries.metaField()); } - if (!Granularities.DEFAULT.equals(timeSeries.granularity())) { + if (!Granularity.DEFAULT.equals(timeSeries.granularity())) { options = options.granularity(timeSeries.granularity()); } collectionOptions = collectionOptions.timeSeries(options); 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 c833e511bf..fb0780c5c8 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 @@ -99,7 +99,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; -import org.springframework.data.mongodb.core.timeseries.Granularities; +import org.springframework.data.mongodb.core.timeseries.Granularity; import org.springframework.data.mongodb.core.validation.Validator; import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; @@ -2436,14 +2436,15 @@ protected MongoCollection doCreateCollection(String collectionName, Do co.validationOptions(options); } - if(collectionOptions.containsKey("timeseries")) { + if (collectionOptions.containsKey("timeseries")) { Document timeSeries = collectionOptions.get("timeseries", Document.class); - com.mongodb.client.model.TimeSeriesOptions options = new com.mongodb.client.model.TimeSeriesOptions(timeSeries.getString("timeField")); - if(timeSeries.containsKey("metaField")) { + com.mongodb.client.model.TimeSeriesOptions options = new com.mongodb.client.model.TimeSeriesOptions( + timeSeries.getString("timeField")); + if (timeSeries.containsKey("metaField")) { options.metaField(timeSeries.getString("metaField")); } - if(timeSeries.containsKey("granularity")) { + if (timeSeries.containsKey("granularity")) { options.granularity(TimeSeriesGranularity.valueOf(timeSeries.getString("granularity").toUpperCase())); } co.timeSeriesOptions(options); @@ -2604,17 +2605,18 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio collectionOptions.getValidationOptions().ifPresent(it -> it.getValidator() // .ifPresent(val -> doc.put("validator", getMappedValidator(val, targetType)))); - collectionOptions.getTimeSeriesOptions().map(operations.forType(targetType)::mapTimeSeriesOptions).ifPresent(it -> { + collectionOptions.getTimeSeriesOptions().map(operations.forType(targetType)::mapTimeSeriesOptions) + .ifPresent(it -> { - Document timeseries = new Document("timeField", it.getTimeField()); - if(StringUtils.hasText(it.getMetaField())) { - timeseries.append("metaField", it.getMetaField()); - } - if(!Granularities.DEFAULT.equals(it.getGranularity())) { - timeseries.append("granularity", it.getGranularity().name().toLowerCase()); - } - doc.put("timeseries", timeseries); - }); + Document timeseries = new Document("timeField", it.getTimeField()); + if (StringUtils.hasText(it.getMetaField())) { + timeseries.append("metaField", it.getMetaField()); + } + if (!Granularity.DEFAULT.equals(it.getGranularity())) { + timeseries.append("granularity", it.getGranularity().name().toLowerCase()); + } + doc.put("timeseries", timeseries); + }); } return doc; @@ -2849,9 +2851,9 @@ private void executeQueryInternal(CollectionCallback> col .initiateFind(getAndPrepareCollection(doGetDatabase(), collectionName), collectionCallback::doInCollection) .iterator()) { - while (cursor.hasNext()) { - callbackHandler.processDocument(cursor.next()); - } + while (cursor.hasNext()) { + callbackHandler.processDocument(cursor.next()); + } } catch (RuntimeException e) { throw potentiallyConvertRuntimeException(e, exceptionTranslator); } @@ -3175,17 +3177,17 @@ private class ReadDocumentCallback implements DocumentCallback { public T doWith(Document document) { - maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); - T entity = reader.read(type, document); + maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); + T entity = reader.read(type, document); - if (entity == null) { - throw new MappingException(String.format("EntityReader %s returned null", reader)); - } + if (entity == null) { + throw new MappingException(String.format("EntityReader %s returned null", reader)); + } - maybeEmitEvent(new AfterConvertEvent<>(document, entity, collectionName)); - entity = maybeCallAfterConvert(entity, document, collectionName); + maybeEmitEvent(new AfterConvertEvent<>(document, entity, collectionName)); + entity = maybeCallAfterConvert(entity, document, collectionName); - return entity; + return entity; } } @@ -3237,8 +3239,8 @@ public T doWith(Document document) { Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, entity) : entity; - maybeEmitEvent(new AfterConvertEvent<>(document, result, collectionName)); - return (T) maybeCallAfterConvert(result, document, collectionName); + maybeEmitEvent(new AfterConvertEvent<>(document, result, collectionName)); + return (T) maybeCallAfterConvert(result, document, collectionName); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 2403e9a394..82a3d12260 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,7 +17,6 @@ import static org.springframework.data.mongodb.core.query.SerializationUtils.*; -import org.springframework.data.mongodb.core.timeseries.Granularities; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.function.Tuple2; @@ -111,6 +110,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter; +import org.springframework.data.mongodb.core.timeseries.Granularity; import org.springframework.data.mongodb.core.validation.Validator; import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; @@ -975,7 +975,8 @@ public Flux aggregate(Aggregation aggregation, String collectionName, Cla return doAggregate(aggregation, collectionName, null, outputType); } - protected Flux doAggregate(Aggregation aggregation, String collectionName, @Nullable Class inputType, Class outputType) { + protected Flux doAggregate(Aggregation aggregation, String collectionName, @Nullable Class inputType, + Class outputType) { Assert.notNull(aggregation, "Aggregation pipeline must not be null!"); Assert.hasText(collectionName, "Collection name must not be null or empty!"); @@ -987,19 +988,18 @@ protected Flux doAggregate(Aggregation aggregation, String collectionName AggregationDefinition ctx = queryOperations.createAggregation(aggregation, inputType); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Streaming aggregation: {} in collection {}", serializeToJsonSafely(ctx.getAggregationPipeline()), collectionName); + LOGGER.debug("Streaming aggregation: {} in collection {}", serializeToJsonSafely(ctx.getAggregationPipeline()), + collectionName); } ReadDocumentCallback readCallback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName); - return execute(collectionName, - collection -> aggregateAndMap(collection, ctx.getAggregationPipeline(), ctx.isOutOrMerge(), options, - readCallback, - ctx.getInputType())); + return execute(collectionName, collection -> aggregateAndMap(collection, ctx.getAggregationPipeline(), + ctx.isOutOrMerge(), options, readCallback, ctx.getInputType())); } private Flux aggregateAndMap(MongoCollection collection, List pipeline, - boolean isOutOrMerge, - AggregationOptions options, ReadDocumentCallback readCallback, @Nullable Class inputType) { + boolean isOutOrMerge, AggregationOptions options, ReadDocumentCallback readCallback, + @Nullable Class inputType) { AggregatePublisher cursor = collection.aggregate(pipeline, Document.class) .allowDiskUse(options.isAllowDiskUse()); @@ -2510,10 +2510,10 @@ protected CreateCollectionOptions convertToCreateCollectionOptions(@Nullable Col TimeSeriesOptions options = new TimeSeriesOptions(it.getTimeField()); - if(StringUtils.hasText(it.getMetaField())) { + if (StringUtils.hasText(it.getMetaField())) { options.metaField(it.getMetaField()); } - if(!Granularities.DEFAULT.equals(it.getGranularity())) { + if (!Granularity.DEFAULT.equals(it.getGranularity())) { options.granularity(TimeSeriesGranularity.valueOf(it.getGranularity().name().toUpperCase())); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java index 8a5fe255e0..d3f694f539 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/TimeSeries.java @@ -22,7 +22,7 @@ import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; -import org.springframework.data.mongodb.core.timeseries.Granularities; +import org.springframework.data.mongodb.core.timeseries.Granularity; /** * Identifies a domain object to be persisted to a MongoDB Time Series collection. @@ -50,8 +50,9 @@ String collection() default ""; /** - * The name of the property which contains the date in each time series document.
      - * {@link Field#name() Annotated fieldnames} will be considered during the mapping process. + * Name of the property which contains the date in each time series document.
      + * Translation of property names to {@link Field#name() annotated fieldnames} will be considered during the mapping + * process. * * @return never {@literal null}. */ @@ -60,19 +61,19 @@ /** * The name of the field which contains metadata in each time series document. Should not be the {@literal id} nor * {@link #timeField()} nor point to an {@literal array} or {@link java.util.Collection}.
      - * {@link Field#name() Annotated fieldnames} will be considered during the mapping process. + * Translation of property names to {@link Field#name() annotated fieldnames} will be considered during the mapping + * process. * * @return empty {@link String} by default. */ String metaField() default ""; /** - * Select the {@link Granularities granularity} parameter to define how data in the time series collection is - * organized. + * Select the {@link Granularity granularity} parameter to define how data in the time series collection is organized. * - * @return {@link Granularities#DEFAULT server default} by default. + * @return {@link Granularity#DEFAULT server default} by default. */ - Granularities granularity() default Granularities.DEFAULT; + Granularity granularity() default Granularity.DEFAULT; /** * Defines the collation to apply when executing a query or creating indexes. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java index c8fe496adb..30ae007fc6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularity.java @@ -16,12 +16,30 @@ package org.springframework.data.mongodb.core.timeseries; /** - * The Granularity of time series data that is closest to the time span between incoming measurements. + * {@link GranularityDefinition Granularities} available for Time Series data. * * @author Christoph Strobl * @since 3.3 */ -public interface Granularity { +public enum Granularity implements GranularityDefinition { - String name(); + /** + * Server default value to indicate no explicit value should be sent. + */ + DEFAULT, + + /** + * High frequency ingestion. + */ + SECONDS, + + /** + * Medium frequency ingestion. + */ + MINUTES, + + /** + * Low frequency ingestion. + */ + HOURS } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/GranularityDefinition.java similarity index 66% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/GranularityDefinition.java index f4cac5232c..06f77cb594 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/Granularities.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/timeseries/GranularityDefinition.java @@ -16,30 +16,12 @@ package org.springframework.data.mongodb.core.timeseries; /** - * {@link Granularity Granularities} available for Time Series data. + * The Granularity of time series data that is closest to the time span between incoming measurements. * * @author Christoph Strobl * @since 3.3 */ -public enum Granularities implements Granularity { +public interface GranularityDefinition { - /** - * Server default value to indicate no explicit value should be sent. - */ - DEFAULT, - - /** - * High frequency ingestion. - */ - SECONDS, - - /** - * Medium frequency ingestion. - */ - MINUTES, - - /** - * Low frequency ingestion. - */ - HOURS + String name(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java new file mode 100644 index 0000000000..901ac1f0dd --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 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 + * + * https://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.*; + +import java.time.Instant; + +import org.junit.jupiter.api.Test; + +import org.springframework.data.mapping.MappingException; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.TimeSeries; + +/** + * Unit tests for {@link EntityOperations}. + * + * @author Mark Paluch + */ +class EntityOperationsUnitTests { + + EntityOperations operations = new EntityOperations(new MongoMappingContext()); + + @Test // GH-3731 + void shouldReportInvalidTimeField() { + assertThatExceptionOfType(MappingException.class) + .isThrownBy(() -> operations.forType(InvalidTimeField.class).getCollectionOptions()) + .withMessageContaining("Time series field 'foo' does not exist"); + } + + @Test // GH-3731 + void shouldReportInvalidMetaField() { + assertThatExceptionOfType(MappingException.class) + .isThrownBy(() -> operations.forType(InvalidMetaField.class).getCollectionOptions()) + .withMessageContaining("Meta field 'foo' does not exist"); + } + + @TimeSeries(timeField = "foo") + static class InvalidTimeField { + + } + + @TimeSeries(timeField = "time", metaField = "foo") + static class InvalidMetaField { + Instant time; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index cc215c956c..147d2e49c3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -19,7 +19,6 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.*; -import com.mongodb.client.model.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -101,7 +100,7 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.core.timeseries.Granularities; +import org.springframework.data.mongodb.core.timeseries.Granularity; import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; @@ -121,6 +120,16 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.CountOptions; +import com.mongodb.client.model.CreateCollectionOptions; +import com.mongodb.client.model.DeleteOptions; +import com.mongodb.client.model.FindOneAndDeleteOptions; +import com.mongodb.client.model.FindOneAndReplaceOptions; +import com.mongodb.client.model.FindOneAndUpdateOptions; +import com.mongodb.client.model.MapReduceAction; +import com.mongodb.client.model.ReplaceOptions; +import com.mongodb.client.model.TimeSeriesGranularity; +import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; @@ -1982,7 +1991,8 @@ void shouldIncludeValueFromNestedShardKeyPath() { ArgumentCaptor filter = ArgumentCaptor.forClass(Bson.class); verify(collection).replaceOne(filter.capture(), any(), any()); - assertThat(filter.getValue()).isEqualTo(new Document("_id", "id-1").append("value", "v1").append("nested.custom-named-field", "cname")); + assertThat(filter.getValue()) + .isEqualTo(new Document("_id", "id-1").append("value", "v1").append("nested.custom-named-field", "cname")); } @Test // DATAMONGO-2341 @@ -2272,7 +2282,8 @@ void createCollectionShouldSetUpTimeSeries() { verify(db).createCollection(any(), options.capture()); assertThat(options.getValue().getTimeSeriesOptions().toString()) - .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").metaField("meta").granularity(TimeSeriesGranularity.HOURS).toString()); + .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").metaField("meta") + .granularity(TimeSeriesGranularity.HOURS).toString()); } class AutogenerateableId { @@ -2370,7 +2381,7 @@ static class Sith { @Field("firstname") String name; } - @Sharded(shardKey = {"value", "nested.customName"}) + @Sharded(shardKey = { "value", "nested.customName" }) static class WithShardKeyPointingToNested { String id; String value; @@ -2384,13 +2395,12 @@ static class TimeSeriesTypeWithDefaults { Instant timestamp; } - @TimeSeries(timeField = "timestamp", metaField = "meta", granularity = Granularities.HOURS) + @TimeSeries(timeField = "timestamp", metaField = "meta", granularity = Granularity.HOURS) static class TimeSeriesType { String id; - @Field("time_stamp") - Instant timestamp; + @Field("time_stamp") Instant timestamp; Object meta; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 17fde7ec32..10e4f1cfcc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -20,15 +20,9 @@ import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.test.util.Assertions.assertThat; -import com.mongodb.client.model.TimeSeriesGranularity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.mongodb.core.MongoTemplateUnitTests.TimeSeriesType; -import org.springframework.data.mongodb.core.MongoTemplateUnitTests.TimeSeriesTypeWithDefaults; -import org.springframework.data.mongodb.core.convert.MongoCustomConversions; -import org.springframework.data.mongodb.core.mapping.TimeSeries; -import org.springframework.data.mongodb.core.timeseries.Granularities; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -77,9 +71,11 @@ import org.springframework.data.mongodb.core.aggregation.Fields; import org.springframework.data.mongodb.core.aggregation.SetOperation; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.TimeSeries; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; import org.springframework.data.mongodb.core.mapping.event.ReactiveAfterConvertCallback; @@ -93,6 +89,7 @@ import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.core.timeseries.Granularity; import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; @@ -106,6 +103,7 @@ import com.mongodb.client.model.FindOneAndReplaceOptions; import com.mongodb.client.model.FindOneAndUpdateOptions; import com.mongodb.client.model.ReplaceOptions; +import com.mongodb.client.model.TimeSeriesGranularity; import com.mongodb.client.model.UpdateOptions; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertManyResult; @@ -951,7 +949,8 @@ void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForF @Test // DATAMONGO-2344, DATAMONGO-2572 void allowSecondaryReadsQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { - template.findDistinct(new Query().allowSecondaryReads(), "name", AutogenerateableId.class, String.class).subscribe(); + template.findDistinct(new Query().allowSecondaryReads(), "name", AutogenerateableId.class, String.class) + .subscribe(); verify(collection).withReadPreference(eq(ReadPreference.primaryPreferred())); } @@ -1428,8 +1427,7 @@ void insertErrorsOnPublisher() { Publisher publisher = Mono.just("data"); - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> template.insert(publisher)); + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> template.insert(publisher)); } @Test // GH-3731 @@ -1453,7 +1451,8 @@ void createCollectionShouldSetUpTimeSeries() { verify(db).createCollection(any(), options.capture()); assertThat(options.getValue().getTimeSeriesOptions().toString()) - .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").metaField("meta").granularity(TimeSeriesGranularity.HOURS).toString()); + .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").metaField("meta") + .granularity(TimeSeriesGranularity.HOURS).toString()); } private void stubFindSubscribe(Document document) { @@ -1520,13 +1519,12 @@ static class TimeSeriesTypeWithDefaults { Instant timestamp; } - @TimeSeries(timeField = "timestamp", metaField = "meta", granularity = Granularities.HOURS) + @TimeSeries(timeField = "timestamp", metaField = "meta", granularity = Granularity.HOURS) static class TimeSeriesType { String id; - @Field("time_stamp") - Instant timestamp; + @Field("time_stamp") Instant timestamp; Object meta; } diff --git a/src/main/asciidoc/reference/time-series.adoc b/src/main/asciidoc/reference/time-series.adoc index ac36e4026e..54601a8ed1 100644 --- a/src/main/asciidoc/reference/time-series.adoc +++ b/src/main/asciidoc/reference/time-series.adoc @@ -1,13 +1,14 @@ [[time-series]] == Time Series -MongoDB 5.0 introduced https://docs.mongodb.com/manual/core/timeseries-collections/[Time Series] collections optimized to efficiently store sequences of measurements. -Those collections need to be actively created before inserting any data. This can be done by manually executing the command, defining time series collection options or extracting options from a `@TimeSeries` annotation as shown in the examples below. +MongoDB 5.0 introduced https://docs.mongodb.com/manual/core/timeseries-collections/[Time Series] collections that are optimized to efficiently store documents over time such as measurements or events. +Those collections need to be created as such before inserting any data. +Collections can be created by either running the `createCollection` command, defining time series collection options or extracting options from a `@TimeSeries` annotation as shown in the examples below. .Create a Time Series Collection ==== .Create a Time Series via the MongoDB Driver -[code, java] +[code,java] ---- template.execute(db -> { @@ -19,14 +20,14 @@ template.execute(db -> { }); ---- -.Create a Time Series Collection with CollectionOptions -[code, java] +.Create a Time Series Collection with `CollectionOptions` +[code,java] ---- template.createCollection("weather", CollectionOptions.timeSeries("timestamp")); ---- .Create a Time Series Collection derived from an Annotation -[code, java] +[code,java] ---- @TimeSeries(collection="weather", timeField = "timestamp") public class Measurement { @@ -41,5 +42,5 @@ template.createCollection(Measurement.class); ==== The snippets above can easily be transferred to the reactive API offering the very same methods. -Just make sure to _subscribe_. +Make sure to properly _subscribe_ to the returned publishers. From 9db9d16cf8348db8ab86e9edf6b48dd2ab367db3 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 16 Jul 2021 10:18:49 +0200 Subject: [PATCH 0468/1381] Updated changelog. See #3681 --- src/main/resources/changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 18ac26a430..929482612f 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,12 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.1.11 (2021-07-16) +-------------------------------------- +* #3689 - Fix Regression in generating queries with nested maps with numeric keys. +* #3688 - Multiple maps with numeric keys in a single update produces the wrong query (Regression). + + Changes in version 3.2.2 (2021-06-22) ------------------------------------- * #3677 - Add missing double quote to GeoJson.java JSDoc header. @@ -3464,5 +3470,6 @@ Repository + From e875f9ea334567408b01fb0233b5854fc035ee93 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 16 Jul 2021 14:08:43 +0200 Subject: [PATCH 0469/1381] Updated changelog. See #3631 --- src/main/resources/changelog.txt | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 929482612f..dff169e6fc 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,6 +1,40 @@ Spring Data MongoDB Changelog ============================= +Changes in version 3.3.0-M1 (2021-07-16) +---------------------------------------- +* #3731 - Add support for creating time series collection. +* #3706 - Upgrade to MongoDB 4.3.0 Drivers. +* #3705 - Adapt to changes in AssertJ 3.20. +* #3702 - `MappingMongoConverter` incorrectly processes an object property of type `org.bson.Document`. +* #3700 - Adapt to consolidated PersistentEntity API. +* #3693 - Upgrade to MongoDB 4.3.0-beta4 Drivers. +* #3689 - Fix Regression in generating queries with nested maps with numeric keys. +* #3688 - Multiple maps with numeric keys in a single update produces the wrong query (Regression). +* #3686 - reading a document with a list with a null element fails with Spring Data Mongo 3.2.2, works with 3.2.1. +* #3684 - Add equals and hashcode to UnwrappedMongoPersistentProperty (fixes #3683). +* #3683 - Memory Leak: instances of UnwrappedMongoPersistentProperty are accumulating in PreferredConstructor.isPropertyParameterCache. +* #3677 - Add missing double quote to GeoJson.java JSDoc header. +* #3674 - Upgrade to Querydsl 5.0. +* #3672 - Directly import JSR305 jar. +* #3670 - `Binary` not deserialized to `byte[]` for property of type `Object`. +* #3668 - Projection on the _id field returns wrong result when using `@MongoId` (MongoDB 4.4). +* #3666 - Documentation references outdated `Mongo` client. +* #3660 - MappingMongoConverter problem: ConversionContext#convert does not try to use custom converters first. +* #3659 - [3.2.1] Indexing Class with Custom Converter -> Couldn't find PersistentEntity for property private [...]. +* #3656 - Fix Build on Java 16. +* #3648 - Inconsistent nullability of read() in templates: not sure if mapper can skip a document. +* #3638 - Introduce template method for easier customization of fragments. +* #3635 - $floor isOrOrNor() return true. +* #3633 - NPE in QueryMapper when use Query with `null` as value. +* #3632 - Fix bullet points in aggregations framework asciidoc. +* #3603 - Update CI to Java 16. +* #3602 - Add support for flexible document references. +* #3543 - Aggregation query method should be able to return `Slice` and `Stream`. +* #3407 - Add an option to @Field annotation to control property write rules [DATAMONGO-2551]. +* #3225 - Add support for Wildcard Indexes [DATAMONGO-2368]. + + Changes in version 3.1.11 (2021-07-16) -------------------------------------- * #3689 - Fix Regression in generating queries with nested maps with numeric keys. @@ -3471,5 +3505,6 @@ Repository + From b6ad32d7d4dd6bd6433695425349c282337c77ee Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 16 Jul 2021 14:08:59 +0200 Subject: [PATCH 0470/1381] Prepare 3.3 M1 (2021.1.0). See #3631 --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index b688f3ee50..382f4470c9 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.6.0-SNAPSHOT + 2.6.0-M1 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.6.0-SNAPSHOT + 2.6.0-M1 4.3.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 07cf1da6a0..624bf48c30 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.2 GA (2021.0.0) +Spring Data MongoDB 3.3 M1 (2021.1.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -27,3 +27,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 4ef1ff6aff2deffb5daa3b8910c4f98ca789660f Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 16 Jul 2021 14:09:25 +0200 Subject: [PATCH 0471/1381] Release version 3.3 M1 (2021.1.0). See #3631 --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 382f4470c9..9a83ef35ef 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M1 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 0033bd11d5..0557a133c7 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M1 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index f62c8dc7f4..d7fbc46ed6 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M1 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 1f157e75bc..6bb6e8ca56 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M1 ../pom.xml From e7f3a2436d24262b587f0c4fc2aa8ae371e688d3 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 16 Jul 2021 14:19:56 +0200 Subject: [PATCH 0472/1381] Prepare next development iteration. See #3631 --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 9a83ef35ef..382f4470c9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M1 + 3.3.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 0557a133c7..0033bd11d5 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M1 + 3.3.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index d7fbc46ed6..f62c8dc7f4 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M1 + 3.3.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 6bb6e8ca56..1f157e75bc 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M1 + 3.3.0-SNAPSHOT ../pom.xml From 4d7ee0e7415be66d59068d5dbfbbb595530acfaa Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 16 Jul 2021 14:19:58 +0200 Subject: [PATCH 0473/1381] After release cleanups. See #3631 --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 382f4470c9..b688f3ee50 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.6.0-M1 + 2.6.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.6.0-M1 + 2.6.0-SNAPSHOT 4.3.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From d2c9b47366aca3da4acbd0221f4c076fb81c0b61 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 22 Jul 2021 09:03:10 +0200 Subject: [PATCH 0474/1381] Fix issues related to Querydsl 5.0 upgrade. Remove overridden methods no longer available in public api. Closes: #3738 --- .../support/QuerydslAbstractMongodbQuery.java | 10 ---------- .../support/SpringDataMongodbQuerySupport.java | 5 ----- 2 files changed, 15 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java index b255d20273..80c485ea3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java @@ -177,16 +177,6 @@ protected Document createSort(List> orderSpecifiers) { return serializer.toSort(orderSpecifiers); } - /** - * Get the actual {@link QueryMixin} delegate. - * - * @return - */ - QueryMixin getQueryMixin() { - return queryMixin; - } - - /** * Returns the {@literal Mongo Shell} representation of the query.
      * The following query diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java index 406019cf4d..be9260df48 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbQuerySupport.java @@ -139,9 +139,4 @@ public String toJson(JsonWriterSettings settings) { protected Document createSort(List> orderSpecifiers) { return serializer.toSort(orderSpecifiers); } - - // TODO: Remove once https://github.com/querydsl/querydsl/pull/2916 is merged - QueryMixin getQueryMixin() { - return superQueryMixin; - } } From 68370c16fb288034f68b2ca2d38f5480e1656e2f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 26 Jul 2021 14:14:31 +0200 Subject: [PATCH 0475/1381] =?UTF-8?q?Run=20unpaged=20query=20using=20Pagea?= =?UTF-8?q?ble.unpaged()=20through=20QuerydslMongoPredicateExecutor.findAl?= =?UTF-8?q?l(=E2=80=A6).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now correctly consider unpaged queries if the Pageable is unpaged. Closes: #3751 Original Pull Request: #3754 --- .../support/QuerydslMongoPredicateExecutor.java | 4 ++++ ...slMongoPredicateExecutorIntegrationTests.java | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java index 95d2299670..d92d7ad129 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java @@ -212,6 +212,10 @@ private SpringDataMongodbQuery createQuery() { */ private SpringDataMongodbQuery applyPagination(SpringDataMongodbQuery query, Pageable pageable) { + if (pageable.isUnpaged()) { + return query; + } + query = query.offset(pageable.getOffset()).limit(pageable.getPageSize()); return applySorting(query, pageable.getSort()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java index 6b46618fdb..782e46b134 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutorIntegrationTests.java @@ -27,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.dao.PermissionDeniedDataAccessException; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -122,6 +124,20 @@ public void findUsingAndShouldWork() { .containsExactly(dave); } + @Test // GH-3751 + public void findPage() { + + assertThat(repository + .findAll(person.lastname.startsWith(oliver.getLastname()).and(person.firstname.startsWith(dave.getFirstname())), + PageRequest.of(0, 10)) + .getContent()).containsExactly(dave); + + assertThat(repository + .findAll(person.lastname.startsWith(oliver.getLastname()).and(person.firstname.startsWith(dave.getFirstname())), + Pageable.unpaged()) + .getContent()).containsExactly(dave); + } + @Test // DATAMONGO-362, DATAMONGO-1848 public void springDataMongodbQueryShouldAllowJoinOnDBref() { From 45971b212c12c67e4233d1b139de06ba088e18ee Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 26 Jul 2021 14:15:24 +0200 Subject: [PATCH 0476/1381] Polishing. Move off deprecated classes. Add unpaged testcase for query by example. Original Pull Request: #3754 --- .../support/QuerydslMongoPredicateExecutor.java | 2 +- .../support/SimpleMongoRepository.java | 2 +- .../support/SimpleMongoRepositoryTests.java | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java index d92d7ad129..569273afb5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslMongoPredicateExecutor.java @@ -27,7 +27,7 @@ import org.springframework.data.querydsl.EntityPathResolver; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.querydsl.SimpleEntityPathResolver; -import org.springframework.data.repository.support.PageableExecutionUtils; +import org.springframework.data.support.PageableExecutionUtils; import org.springframework.util.Assert; import com.querydsl.core.NonUniqueResultException; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index 4ffba8a6a3..1443474b8f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -36,7 +36,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; -import org.springframework.data.repository.support.PageableExecutionUtils; +import org.springframework.data.support.PageableExecutionUtils; import org.springframework.data.util.StreamUtils; import org.springframework.data.util.Streamable; import org.springframework.lang.Nullable; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 135b6b3888..61cd78ea93 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -30,10 +30,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.ExampleMatcher.*; +import org.springframework.data.domain.Pageable; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; @@ -177,6 +178,19 @@ void findByExampleShouldLookUpEntriesCorrectly() { assertThat(result.getTotalPages()).isEqualTo(1); } + @Test // GH-3751 + void findByExampleShouldReturnUnpagedResults() { + + Person sample = new Person(); + sample.setLastname("Matthews"); + trimDomainType(sample, "id", "createdAt", "email"); + + Page result = repository.findAll(Example.of(sample), Pageable.unpaged()); + + assertThat(result.getContent()).hasSize(2).contains(dave, oliver); + assertThat(result.getTotalPages()).isEqualTo(1); + } + @Test // DATAMONGO-1464 void findByExampleMultiplePagesShouldLookUpEntriesCorrectly() { From 454afd9877b6a7d2c164461f766a294cd907141f Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Aug 2021 15:02:56 +0200 Subject: [PATCH 0477/1381] Prepare 3.3 M2 (2021.1.0). See #3736 --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index b688f3ee50..b6477961a1 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.6.0-SNAPSHOT + 2.6.0-M2 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.6.0-SNAPSHOT + 2.6.0-M2 4.3.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 624bf48c30..29628c3570 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.3 M1 (2021.1.0) +Spring Data MongoDB 3.3 M2 (2021.1.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -27,4 +27,5 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 87ab1ac48ceaec1f014a6f50148cb6b4d9c20544 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Aug 2021 15:03:17 +0200 Subject: [PATCH 0478/1381] Release version 3.3 M2 (2021.1.0). See #3736 --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index b6477961a1..ff938bcceb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M2 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 0033bd11d5..31260b443f 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M2 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index f62c8dc7f4..8e0bf96e21 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M2 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 1f157e75bc..42bf7aa081 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M2 ../pom.xml From 828c07416794d75c8e41753a53e1c2b3d96ac565 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Aug 2021 15:16:21 +0200 Subject: [PATCH 0479/1381] Prepare next development iteration. See #3736 --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ff938bcceb..b6477961a1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M2 + 3.3.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 31260b443f..0033bd11d5 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M2 + 3.3.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 8e0bf96e21..f62c8dc7f4 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M2 + 3.3.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 42bf7aa081..1f157e75bc 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M2 + 3.3.0-SNAPSHOT ../pom.xml From 7538b1a1a57a6fb4d1a2cfc54fda095a5d29ee8e Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Aug 2021 15:16:23 +0200 Subject: [PATCH 0480/1381] After release cleanups. See #3736 --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index b6477961a1..b688f3ee50 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.6.0-M2 + 2.6.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.6.0-M2 + 2.6.0-SNAPSHOT 4.3.0 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 1d943d62a370267244cdabbb04160418532671fe Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 26 Jul 2021 13:10:15 +0200 Subject: [PATCH 0481/1381] Fix build on Java 16. Make sure to use an initialized MappingContext. Closes: #3749 Original pull request: #3752. --- .../core/EntityOperationsUnitTests.java | 3 +- .../data/mongodb/core/MongoTemplateTests.java | 2 +- .../test/util/MappingContextConfigurer.java | 50 ++++++++++++ .../test/util/MongoConverterConfigurer.java | 40 ++++++++++ .../test/util/MongoTestMappingContext.java | 78 +++++++++++++++++++ .../mongodb/test/util/MongoTestTemplate.java | 2 +- .../util/MongoTestTemplateConfiguration.java | 51 +----------- .../test/util/ReactiveMongoTestTemplate.java | 2 +- 8 files changed, 174 insertions(+), 54 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MappingContextConfigurer.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoConverterConfigurer.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestMappingContext.java diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java index 901ac1f0dd..160a598bc7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/EntityOperationsUnitTests.java @@ -24,6 +24,7 @@ import org.springframework.data.mapping.MappingException; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.TimeSeries; +import org.springframework.data.mongodb.test.util.MongoTestMappingContext; /** * Unit tests for {@link EntityOperations}. @@ -32,7 +33,7 @@ */ class EntityOperationsUnitTests { - EntityOperations operations = new EntityOperations(new MongoMappingContext()); + EntityOperations operations = new EntityOperations(MongoTestMappingContext.newTestContext()); @Test // GH-3731 void shouldReportInvalidTimeField() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index f5521008f8..28cdaa4830 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -138,7 +138,7 @@ public class MongoTemplateTests { cfg.configureMappingContext(it -> { it.autocreateIndex(false); - it.intitalEntitySet(AuditablePerson.class); + it.initialEntitySet(AuditablePerson.class); }); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MappingContextConfigurer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MappingContextConfigurer.java new file mode 100644 index 0000000000..75169f5e45 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MappingContextConfigurer.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 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 + * + * https://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.test.util; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.lang.Nullable; + +/** + * Utility to configure {@link org.springframework.data.mongodb.core.mapping.MongoMappingContext} properties. + * + * @author Christoph Strobl + */ +public class MappingContextConfigurer { + + private @Nullable Set> intitalEntitySet; + boolean autocreateIndex = false; + + public void autocreateIndex(boolean autocreateIndex) { + this.autocreateIndex = autocreateIndex; + } + + public void initialEntitySet(Set> initialEntitySet) { + this.intitalEntitySet = initialEntitySet; + } + + public void initialEntitySet(Class... initialEntitySet) { + this.intitalEntitySet = new HashSet<>(Arrays.asList(initialEntitySet)); + } + + Set> initialEntitySet() { + return intitalEntitySet != null ? intitalEntitySet : Collections.emptySet(); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoConverterConfigurer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoConverterConfigurer.java new file mode 100644 index 0000000000..7129d9951a --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoConverterConfigurer.java @@ -0,0 +1,40 @@ +/* + * Copyright 2021 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 + * + * https://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.test.util; + +import java.util.Arrays; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.CustomConversions; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; + +/** + * Utility to configure {@link MongoCustomConversions}. + * + * @author Christoph Strobl + */ +public class MongoConverterConfigurer { + + CustomConversions customConversions; + + public void customConversions(CustomConversions customConversions) { + this.customConversions = customConversions; + } + + public void customConverters(Converter... converters) { + customConversions(new MongoCustomConversions(Arrays.asList(converters))); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestMappingContext.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestMappingContext.java new file mode 100644 index 0000000000..f9701d24aa --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestMappingContext.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021 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 + * + * https://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.test.util; + +import java.util.Collections; +import java.util.function.Consumer; + +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; + +/** + * @author Christoph Strobl + */ +public class MongoTestMappingContext extends MongoMappingContext { + + private MappingContextConfigurer contextConfigurer; + private MongoConverterConfigurer converterConfigurer; + + public static MongoTestMappingContext newTestContext() { + return new MongoTestMappingContext(conig -> {}).init(); + } + + public MongoTestMappingContext(MappingContextConfigurer contextConfig) { + + this.contextConfigurer = contextConfig; + this.converterConfigurer = new MongoConverterConfigurer(); + } + + public MongoTestMappingContext(Consumer contextConfig) { + + this(new MappingContextConfigurer()); + contextConfig.accept(contextConfigurer); + } + + public MongoTestMappingContext customConversions(MongoConverterConfigurer converterConfig) { + + this.converterConfigurer = converterConfig; + return this; + } + + public MongoTestMappingContext customConversions(Consumer converterConfig) { + + converterConfig.accept(converterConfigurer); + return this; + } + + public MongoTestMappingContext init() { + + setInitialEntitySet(contextConfigurer.initialEntitySet()); + setAutoIndexCreation(contextConfigurer.autocreateIndex); + if (converterConfigurer.customConversions != null) { + setSimpleTypeHolder(converterConfigurer.customConversions.getSimpleTypeHolder()); + } else { + setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); + } + + super.afterPropertiesSet(); + return this; + } + + @Override + public void afterPropertiesSet() { + init(); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java index ff1363965d..c612319e55 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java @@ -50,7 +50,7 @@ public MongoTestTemplate(MongoClient client, String database, Class... initia cfg.configureMappingContext(it -> { it.autocreateIndex(false); - it.intitalEntitySet(initialEntities); + it.initialEntitySet(initialEntities); }); }); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java index ee75da8b19..b50ff88133 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java @@ -16,20 +16,15 @@ package org.springframework.data.mongodb.test.util; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.convert.converter.Converter; import org.springframework.data.auditing.IsNewAwareAuditingHandler; -import org.springframework.data.convert.CustomConversions; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; @@ -115,16 +110,7 @@ ApplicationContext getApplicationContext() { MongoMappingContext mappingContext() { if (mappingContext == null) { - - mappingContext = new MongoMappingContext(); - mappingContext.setInitialEntitySet(mappingContextConfigurer.initialEntitySet()); - mappingContext.setAutoIndexCreation(mappingContextConfigurer.autocreateIndex); - if(mongoConverterConfigurer.customConversions != null) { - mappingContext.setSimpleTypeHolder(mongoConverterConfigurer.customConversions.getSimpleTypeHolder()); - } else { - mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder()); - } - mappingContext.afterPropertiesSet(); + mappingContext = new MongoTestMappingContext(mappingContextConfigurer).customConversions(mongoConverterConfigurer).init(); } return mappingContext; @@ -222,41 +208,6 @@ public void defaultDb(String defaultDatabase) { } } - public static class MongoConverterConfigurer { - - CustomConversions customConversions; - - public void customConversions(CustomConversions customConversions) { - this.customConversions = customConversions; - } - - public void customConverters(Converter... converters) { - customConversions(new MongoCustomConversions(Arrays.asList(converters))); - } - } - - public static class MappingContextConfigurer { - - Set> intitalEntitySet; - boolean autocreateIndex = false; - - public void autocreateIndex(boolean autocreateIndex) { - this.autocreateIndex = autocreateIndex; - } - - public void intitalEntitySet(Set> intitalEntitySet) { - this.intitalEntitySet = intitalEntitySet; - } - - public void intitalEntitySet(Class... initialEntitySet) { - this.intitalEntitySet = new HashSet<>(Arrays.asList(initialEntitySet)); - } - - Set> initialEntitySet() { - return intitalEntitySet != null ? intitalEntitySet : Collections.emptySet(); - } - } - public static class AuditingConfigurer { Function auditingHandlerFunction; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java index 9e7d2bbbfa..774493322e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java @@ -56,7 +56,7 @@ public ReactiveMongoTestTemplate(MongoClient client, String database, Class.. cfg.configureMappingContext(it -> { it.autocreateIndex(false); - it.intitalEntitySet(initialEntities); + it.initialEntitySet(initialEntities); }); }); } From 255491c4468898be440cf51e727c53669e6de9ef Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 23 Aug 2021 09:31:25 +0200 Subject: [PATCH 0482/1381] Upgrade to MongoDB 4.3.1 Drivers. Closes: #3778 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b688f3ee50..5d28c8a5c5 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.6.0-SNAPSHOT - 4.3.0 + 4.3.1 ${mongo} 1.19 From 23254c10dc7a11b5fe1c7937c889d42baa3fcee0 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 16 Jul 2021 11:37:08 +0200 Subject: [PATCH 0483/1381] Add support for `$setWindowFields` aggregation stage. Add a SetWindowFieldsOperation to the aggregation framework. The builder API allows fluent declaration of the aggregation stage as shown in the sample below. SetWindowFieldsOperation.builder() .partitionByField("state") .sortBy(Sort.by(Direction.ASC, "date")) .output(AccumulatorOperators.valueOf("qty").sum()) .within(Windows.documents().fromUnbounded().toCurrent().build()) .as("cumulativeQuantityForState") .build(); Closes #3711 Original pull request: #3739. --- .../aggregation/SetWindowFieldsOperation.java | 783 ++++++++++++++++++ .../SetWindowFieldsOperationTests.java | 132 +++ .../SetWindowFieldsOperationUnitTests.java | 111 +++ 3 files changed, 1026 insertions(+) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java new file mode 100644 index 0000000000..0f0909beb2 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java @@ -0,0 +1,783 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.bson.Document; +import org.springframework.data.domain.Sort; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * @author Christoph Strobl + * @since 3.3 + * @see https://docs.mongodb.com/manual/reference/operator/aggregation/setWindowFields/ + */ +public class SetWindowFieldsOperation + implements AggregationOperation, FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation { + + @Nullable // + private Object partitionBy; + + @Nullable // + private AggregationOperation sortBy; + + private WindowOutput output; + + /** + * Create a new {@link SetWindowFieldsOperation} with given args. + * + * @param partitionBy The field or {@link AggregationExpression} to group by. + * @param sortBy the {@link SortOperation operation} to sort the documents by in the partition. + * @param output the {@link WindowOutput} containing the fields to add and the rules to calculate their respective + * values. + */ + public SetWindowFieldsOperation(@Nullable Object partitionBy, @Nullable AggregationOperation sortBy, + WindowOutput output) { + + this.partitionBy = partitionBy; + this.sortBy = sortBy; + this.output = output; + } + + /** + * Obtain a {@link SetWindowFieldsOperationBuilder builder} to create a {@link SetWindowFieldsOperation}. + * + * @return new instance of {@link SetWindowFieldsOperationBuilder}. + */ + public static SetWindowFieldsOperationBuilder builder() { + return new SetWindowFieldsOperationBuilder(); + } + + @Override + public ExposedFields getFields() { + return ExposedFields.nonSynthetic(Fields.from(output.fields.toArray(new Field[0]))); + } + + @Override + public Document toDocument(AggregationOperationContext context) { + + Document $setWindowFields = new Document(); + if (partitionBy != null) { + if (partitionBy instanceof AggregationExpression) { + $setWindowFields.append("partitionBy", ((AggregationExpression) partitionBy).toDocument(context)); + } else if (partitionBy instanceof Field) { + $setWindowFields.append("partitionBy", context.getReference((Field) partitionBy).toString()); + } else { + $setWindowFields.append("partitionBy", partitionBy); + } + } + + if (sortBy != null) { + $setWindowFields.append("sortBy", sortBy.toDocument(context).get(sortBy.getOperator())); + } + + Document output = new Document(); + for (ComputedField field : this.output.fields) { + + Document fieldOperation = field.getWindowOperator().toDocument(context); + if (field.window != null) { + fieldOperation.put("window", field.window.toDocument(context)); + } + output.append(field.getName(), fieldOperation); + } + $setWindowFields.append("output", output); + + return new Document(getOperator(), $setWindowFields); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#getOperator() + */ + @Override + public String getOperator() { + return "$setWindowFields"; + } + + /** + * {@link WindowOutput} defines output of {@literal $setWindowFields} stage by defining the {@link ComputedField + * field(s)} to append to the documents in the output. + */ + public static class WindowOutput { + + private List fields; + + /** + * Create a new output containing the single given {@link ComputedField field}. + * + * @param outputField must not be {@literal null}. + */ + public WindowOutput(ComputedField outputField) { + + Assert.notNull(outputField, "OutputField must not be null!"); + this.fields = new ArrayList<>(); + this.fields.add(outputField); + } + + /** + * Append the given {@link ComputedField field} to the outptut. + * + * @param field must not be {@literal null}. + * @return this. + */ + public WindowOutput append(ComputedField field) { + + Assert.notNull(field, "Field must not be null!"); + fields.add(field); + return this; + } + + /** + * Append the given {@link AggregationExpression} as a {@link ComputedField field} in a fluent way. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link ComputedFieldAppender}. + * @see #append(ComputedField) + */ + public ComputedFieldAppender append(AggregationExpression expression) { + + return new ComputedFieldAppender() { + + @Nullable private Window window; + + @Override + public WindowOutput as(String fieldname) { + + return WindowOutput.this.append(new ComputedField(fieldname, expression, window)); + } + + @Override + public ComputedFieldAppender within(Window window) { + this.window = window; + return this; + } + }; + } + + /** + * Tiny little helper to allow fluent API usage for {@link #append(ComputedField)}. + */ + interface ComputedFieldAppender { + + /** + * Specify the target field name. + * + * @param fieldname the name of field to add to the target document. + * @return the {@link WindowOutput} that started the append operation. + */ + WindowOutput as(String fieldname); + + /** + * Specify the window boundaries. + * + * @param window must not be {@literal null}. + * @return this. + */ + ComputedFieldAppender within(Window window); + } + } + + /** + * A {@link Field} that the result of a computation done via an {@link AggregationExpression}. + * + * @author Christoph Strobl + */ + public static class ComputedField implements Field { + + private String name; + private AggregationExpression windowOperator; + + @Nullable // + private Window window; + + /** + * Create a new {@link ComputedField}. + * + * @param name the target field name. + * @param windowOperator the expression to calculate the field value. + */ + public ComputedField(String name, AggregationExpression windowOperator) { + this(name, windowOperator, null); + } + + /** + * Create a new {@link ComputedField}. + * + * @param name the target field name. + * @param windowOperator the expression to calculate the field value. + * @param window the boundaries to operate within. Can be {@literal null}. + */ + public ComputedField(String name, AggregationExpression windowOperator, @Nullable Window window) { + + this.name = name; + this.windowOperator = windowOperator; + this.window = window; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getTarget() { + return getName(); + } + + @Override + public boolean isAliased() { + return false; + } + + public AggregationExpression getWindowOperator() { + return windowOperator; + } + + public Window getWindow() { + return window; + } + } + + /** + * Quick access to {@link DocumentWindow documents} and {@literal RangeWindow range} {@link Window windows}. + * + * @author Christoph Strobl + */ + public interface Windows { + + /** + * Create a document window relative to the position of the current document. + * + * @param lower an integer for a position relative to the current document, {@literal current} or + * {@literal unbounded}. + * @param upper an integer for a position relative to the current document, {@literal current} or + * {@literal unbounded}. + * @return new instance of {@link DocumentWindow}. + */ + static DocumentWindow documents(Object lower, Object upper) { + return new DocumentWindow(lower, upper); + } + + /** + * Create a range window defined based on sort expression. + * + * @param lower a numeric value to add the sort by field value of the current document, {@literal current} or + * {@literal unbounded}. + * @param upper a numeric value to add the sort by field value of the current document, {@literal current} or + * {@literal unbounded}. + * @return new instance of {@link RangeWindow}. + */ + static RangeWindow range(Object lower, Object upper, @Nullable WindowUnit unit) { + return new RangeWindow(lower, upper, unit); + } + + /** + * Create a range window based on the {@link Sort sort value} of the current document via a fluent API. + * + * @return new instance of {@link RangeWindowBuilder}. + */ + static RangeWindowBuilder range() { + return new RangeWindowBuilder(); + } + + /** + * Create a document window relative to the position of the current document via a fluent API. + * + * @return new instance of {@link DocumentWindowBuilder}. + */ + static DocumentWindowBuilder documents() { + return new DocumentWindowBuilder(); + } + } + + /** + * A {@link Window} to be used for {@link ComputedField#getWindow() ComputedField}. + */ + public interface Window { + + /** + * The upper (inclusive) boundary. + * + * @return + */ + Object getUpper(); + + /** + * The lower (inclusive) boundary. + * + * @return + */ + Object getLower(); + + /** + * Obtain the document representation of the window in a default {@link AggregationOperationContext context}. + * + * @return never {@literal null}. + */ + default Document toDocument() { + return toDocument(Aggregation.DEFAULT_CONTEXT); + } + + /** + * Obtain the document representation of the window in the given {@link AggregationOperationContext context}. + * + * @return never {@literal null}. + */ + Document toDocument(AggregationOperationContext ctx); + } + + /** + * Builder API for a {@link RangeWindow}. + * + * @author Christoph Strobl + */ + public static class RangeWindowBuilder { + + @Nullable // + private Object upper; + + @Nullable // + private Object lower; + + @Nullable // + private WindowUnit unit; + + /** + * The upper (inclusive) range limit based on the sortBy field. + * + * @param upper eg. {@literal current} or {@literal unbounded}. + * @return this. + */ + public RangeWindowBuilder to(String upper) { + + this.upper = upper; + return this; + } + + /** + * The lower (inclusive) range limit based on the sortBy field. + * + * @param lower eg. {@literal current} or {@literal unbounded}. + * @return this. + */ + public RangeWindowBuilder from(String lower) { + + this.lower = lower; + return this; + } + + /** + * The upper (inclusive) range limit value to add to the value based on the sortBy field. + * + * @param upper + * @return this. + */ + public RangeWindowBuilder to(Number upper) { + + this.upper = upper; + return this; + } + + /** + * The lower (inclusive) range limit value to add to the value based on the sortBy field. + * + * @param lower + * @return this. + */ + public RangeWindowBuilder from(Number lower) { + + this.lower = lower; + return this; + } + + /** + * Use {@literal current} as {@link #from(String) lower} limit. + * + * @return this. + */ + public RangeWindowBuilder fromCurrent() { + return from("current"); + } + + /** + * Use {@literal unbounded} as {@link #from(String) lower} limit. + * + * @return this. + */ + public RangeWindowBuilder fromUnbounded() { + return from("unbounded"); + } + + /** + * Use {@literal current} as {@link #to(String) upper} limit. + * + * @return this. + */ + public RangeWindowBuilder toCurrent() { + return to("current"); + } + + /** + * Use {@literal unbounded} as {@link #to(String) upper} limit. + * + * @return this. + */ + public RangeWindowBuilder toUnbounded() { + return to("unbounded"); + } + + /** + * Set the {@link WindowUnit unit} or measure for the given {@link Window}. + * + * @param windowUnit must not be {@literal null}. Can be on of {@link Windows}. + * @return this. + */ + public RangeWindowBuilder unit(WindowUnit windowUnit) { + + this.unit = unit; + return this; + } + + /** + * Build the {@link RangeWindow}. + * + * @return new instance of {@link RangeWindow}. + */ + public RangeWindow build() { + return new RangeWindow(lower, upper, unit); + } + } + + /** + * Builder API for a {@link RangeWindow}. + * + * @author Christoph Strobl + */ + public static class DocumentWindowBuilder { + + @Nullable // + private Object upper; + + @Nullable // + private Object lower; + + public DocumentWindowBuilder from(Number lower) { + + this.lower = lower; + return this; + } + + public DocumentWindowBuilder fromCurrent() { + return from("current"); + } + + public DocumentWindowBuilder fromUnbounded() { + return from("unbounded"); + } + + public DocumentWindowBuilder to(String upper) { + + this.upper = upper; + return this; + } + + /** + * The lower (inclusive) range limit based on current document. + * + * @param lower eg. {@literal current} or {@literal unbounded}. + * @return this. + */ + public DocumentWindowBuilder from(String lower) { + + this.lower = lower; + return this; + } + + /** + * The upper (inclusive) range limit based on current document. + * + * @param upper eg. {@literal current} or {@literal unbounded}. + * @return this. + */ + public DocumentWindowBuilder to(Number upper) { + + this.upper = upper; + return this; + } + + public DocumentWindowBuilder toCurrent() { + return to("current"); + } + + public DocumentWindowBuilder toUnbounded() { + return to("unbounded"); + } + + public DocumentWindow build() { + return new DocumentWindow(lower, upper); + } + } + + /** + * Common base class for {@link Window} implementation. + * + * @author Christoph Strobl + */ + abstract static class WindowImp implements Window { + + private final Object upper; + private final Object lower; + + protected WindowImp(Object lower, Object upper) { + this.upper = upper; + this.lower = lower; + } + + @Override + public Object getUpper() { + return upper; + } + + @Override + public Object getLower() { + return lower; + } + } + + /** + * {@link Window} implementation based on the current document. + * + * @author Christoph Strobl + */ + public static class DocumentWindow extends WindowImp { + + DocumentWindow(Object lower, Object upper) { + super(lower, upper); + } + + @Override + public Document toDocument(AggregationOperationContext ctx) { + return new Document("documents", Arrays.asList(getLower(), getUpper())); + } + } + + /** + * {@link Window} implementation based on the sort fields. + * + * @author Christoph Strobl + */ + public static class RangeWindow extends WindowImp { + + @Nullable // + private WindowUnit unit; + + protected RangeWindow(Object lower, Object upper, WindowUnit unit) { + + super(lower, upper); + this.unit = unit; + } + + @Override + public Document toDocument(AggregationOperationContext ctx) { + + Document range = new Document("range", new Object[] { getLower(), getUpper() }); + if (unit != null && !WindowUnits.DEFAULT.equals(unit)) { + range.append("unit", unit.name().toLowerCase()); + } + return range; + } + } + + /** + * The actual time unit to apply to a {@link Window}. + */ + public interface WindowUnit { + String name(); + } + + /** + * Quick access to available {@link WindowUnit units}. + */ + public enum WindowUnits implements WindowUnit { + DEFAULT, YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, MILLISECOND + } + + /** + * A fluent builder to create a {@link SetWindowFieldsOperation}. + * + * @author Christoph Strobl + */ + public static class SetWindowFieldsOperationBuilder { + + private Object partitionBy; + private SortOperation sortOperation; + private WindowOutput output; + + /** + * Specify the field to group by. + * + * @param fieldName must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder partitionByField(String fieldName) { + return partitionBy(Fields.field("$" + fieldName, fieldName)); + } + + /** + * Specify the {@link AggregationExpression expression} to group by. + * + * @param expression must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder partitionByExpression(AggregationExpression expression) { + return partitionBy(expression); + } + + /** + * Sort {@link Sort.Direction#ASC ascending} by the given fields. + * + * @param fields must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder sortBy(String... fields) { + return sortBy(Sort.by(fields)); + } + + /** + * Set the sort order. + * + * @param sort must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder sortBy(Sort sort) { + return sortBy(new SortOperation(sort)); + } + + /** + * Set the {@link SortOperation} to use. + * + * @param sort must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder sortBy(SortOperation sort) { + + this.sortOperation = sort; + return this; + } + + /** + * Define the actual output computation. + * + * @param output must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder output(WindowOutput output) { + + this.output = output; + return this; + } + + /** + * Add a field capturing the result of the given {@link AggregationExpression expression} to the output. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link WindowChoice}. + */ + public WindowChoice output(AggregationExpression expression) { + + return new WindowChoice() { + + @Nullable private Window window; + + @Override + public As within(Window window) { + + this.window = window; + return this; + } + + @Override + public SetWindowFieldsOperationBuilder as(String targetFieldName) { + + ComputedField computedField = new ComputedField(targetFieldName, expression, window); + + if (SetWindowFieldsOperationBuilder.this.output == null) { + SetWindowFieldsOperationBuilder.this.output = new WindowOutput(computedField); + } else { + SetWindowFieldsOperationBuilder.this.output.append(computedField); + } + + return SetWindowFieldsOperationBuilder.this; + } + }; + } + + /** + * Interface to capture field name used to capture the computation result. + */ + public interface As { + + /** + * Define the target name field name to hold the computation result. + * + * @param targetFieldName must not be {@literal null}. + * @return the starting point {@link SetWindowFieldsOperationBuilder builder} instance. + */ + SetWindowFieldsOperationBuilder as(String targetFieldName); + } + + /** + * Interface to capture an optional {@link Window} applicable to the field computation. + */ + public interface WindowChoice extends As { + + /** + * Specify calculation boundaries. + * + * @param window must not be {@literal null}. + * @return never {@literal null}. + */ + As within(Window window); + + } + + /** + * Partition by a value that transaltes to a valid mongodb expression. + * + * @param value must not be {@literal null}. + * @return this. + */ + public SetWindowFieldsOperationBuilder partitionBy(Object value) { + + partitionBy = value; + return this; + } + + /** + * Obtain a new instance of {@link SetWindowFieldsOperation} with previously set arguments. + * + * @return new instance of {@link SetWindowFieldsOperation}. + */ + public SetWindowFieldsOperation build() { + return new SetWindowFieldsOperation(partitionBy, sortOperation, output); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java new file mode 100644 index 0000000000..b88e0479a3 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java @@ -0,0 +1,132 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.bson.Document; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.data.annotation.Id; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.mongodb.core.aggregation.DateOperators.Year; +import org.springframework.data.mongodb.core.aggregation.SetWindowFieldsOperation.Windows; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; + +/** + * @author Christoph Strobl + */ +@ExtendWith(MongoTemplateExtension.class) +@EnableIfMongoServerVersion(isGreaterThanEqual = "5.0") +class SetWindowFieldsOperationTests { + + @Template // + private static MongoTestTemplate mongoTemplate; + + @AfterEach + void afterEach() { + mongoTemplate.flush(CakeSale.class); + } + + @Test // GH-3711 + void executesSetWindowFieldsOperationCorrectly() { + + initCakeSales(); + + SetWindowFieldsOperation setWindowFieldsOperation = SetWindowFieldsOperation.builder() // + .partitionByField("state") // resolves to field ref "$state" + .sortBy(Sort.by(Direction.ASC, "date")) // resolves to "orderDate" + .output(AccumulatorOperators.valueOf("qty").sum()) // resolves to "$quantity" + .within(Windows.documents().fromUnbounded().toCurrent().build()) // + .as("cumulativeQuantityForState") // + .build(); // + + AggregationResults results = mongoTemplate.aggregateAndReturn(Document.class) + .by(Aggregation.newAggregation(CakeSale.class, setWindowFieldsOperation)).all(); + + assertThat(results.getMappedResults()).map(it -> it.get("cumulativeQuantityForState")).contains(162, 282, 427, 134, + 238, 378); + } + + @Test // GH-3711 + void executesSetWindowFieldsOperationWithPartitionExpressionCorrectly() { + + initCakeSales(); + + SetWindowFieldsOperation setWindowFieldsOperation = SetWindowFieldsOperation.builder() // + .partitionByExpression(Year.yearOf("date")) // resolves to $year: "$orderDate" + .sortBy(Sort.by(Direction.ASC, "date")) // resolves to "orderDate" + .output(AccumulatorOperators.valueOf("qty").sum()) // resolves to "$quantity" + .within(Windows.documents().fromUnbounded().toCurrent().build()) // + .as("cumulativeQuantityForState") // + .build(); // + + AggregationResults results = mongoTemplate.aggregateAndReturn(Document.class) + .by(Aggregation.newAggregation(CakeSale.class, setWindowFieldsOperation)).all(); + + assertThat(results.getMappedResults()).map(it -> it.get("cumulativeQuantityForState")).contains(134, 296, 104, 224, + 145, 285); + } + + void initCakeSales() { + + mongoTemplate.execute(CakeSale.class, collection -> { + + List source = Arrays.asList(Document.parse( + "{ _id: 0, type: \"chocolate\", orderDate: { $date : \"2020-05-18T14:10:30Z\" }, state: \"CA\", price: 13, quantity: 120 }"), + Document.parse( + "{ _id: 1, type: \"chocolate\", orderDate: { $date : \"2021-03-20T11:30:05Z\"}, state: \"WA\", price: 14, quantity: 140 }"), + Document.parse( + "{ _id: 2, type: \"vanilla\", orderDate: { $date : \"2021-01-11T06:31:15Z\"}, state: \"CA\", price: 12, quantity: 145 }"), + Document.parse( + "{ _id: 3, type: \"vanilla\", orderDate: { $date : \"2020-02-08T13:13:23Z\"}, state: \"WA\", price: 13, quantity: 104 }"), + Document.parse( + "{ _id: 4, type: \"strawberry\", orderDate: { $date : \"2019-05-18T16:09:01Z\"}, state: \"CA\", price: 41, quantity: 162 }"), + Document.parse( + "{ _id: 5, type: \"strawberry\", orderDate: { $date : \"2019-01-08T06:12:03Z\"}, state: \"WA\", price: 43, quantity: 134 }")); + + collection.insertMany(source); + return "OK"; + }); + } + + @lombok.Data + static class CakeSale { + + @Id Integer id; + + String state; + + @Field("orderDate") // + Date date; + + @Field("quantity") // + Integer qty; + + String type; + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java new file mode 100644 index 0000000000..87e3f8f54c --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Date; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; +import org.springframework.data.mongodb.core.aggregation.SetWindowFieldsOperation.Windows; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + */ +public class SetWindowFieldsOperationUnitTests { + + @Test // GH-3711 + void rendersTargetFieldNamesCorrectly() { + + SetWindowFieldsOperation setWindowFieldsOperation = SetWindowFieldsOperation.builder() // + .partitionByField("state") // resolves to field ref "$state" + .sortBy(Sort.by(Direction.ASC, "date")) // resolves to "orderDate" + .output(AccumulatorOperators.valueOf("qty").sum()) // resolves to "$quantity" + .within(Windows.documents().fromUnbounded().toCurrent().build()) // + .as("cumulativeQuantityForState") // + .build(); // + + Document document = setWindowFieldsOperation.toDocument(contextFor(CakeSale.class)); + assertThat(document).isEqualTo(Document.parse( + "{ $setWindowFields: { partitionBy: \"$state\", sortBy: { orderDate: 1 }, output: { cumulativeQuantityForState: { $sum: \"$quantity\", window: { documents: [ \"unbounded\", \"current\" ] } } } } }")); + } + + @Test // GH-3711 + void exposesTargetFieldNames() { + + SetWindowFieldsOperation setWindowFieldsOperation = SetWindowFieldsOperation.builder() // + .output(AccumulatorOperators.valueOf("qty").sum()) // resolves to "$quantity" + .within(Windows.documents().fromUnbounded().toCurrent().build()) // + .as("f1") // + .output(AccumulatorOperators.valueOf("qty").avg()) // resolves to "$quantity" + .within(Windows.documents().from(-1).to(0).build()) // + .as("f2") // + .build(); // + + assertThat(setWindowFieldsOperation.getFields()).map(ExposedField::getName).containsExactly("f1", "f2"); + } + + @Test // GH-3711 + void rendersMuiltipleOutputFields() { + + SetWindowFieldsOperation setWindowFieldsOperation = SetWindowFieldsOperation.builder() // + .output(AccumulatorOperators.valueOf("qty").sum()) // resolves to "$quantity" + .within(Windows.documents().fromUnbounded().toCurrent().build()) // + .as("f1") // + .output(AccumulatorOperators.valueOf("qty").avg()) // resolves to "$quantity" + .within(Windows.documents().from(-1).to(0).build()) // + .as("f2") // + .build(); // + + Document document = setWindowFieldsOperation.toDocument(contextFor(CakeSale.class)); + assertThat(document).isEqualTo(Document.parse( + "{ $setWindowFields: { output: { f1 : { $sum: \"$quantity\", window: { documents: [ \"unbounded\", \"current\" ] } }, f2 : { $avg: \"$quantity\", window: { documents: [ -1, 0 ] } } } } }")); + } + + private static AggregationOperationContext contextFor(@Nullable Class type) { + + if (type == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + MappingMongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, + new MongoMappingContext()); + mongoConverter.afterPropertiesSet(); + + return new TypeBasedAggregationOperationContext(type, mongoConverter.getMappingContext(), + new QueryMapper(mongoConverter)); + } + + static class CakeSale { + + String state; + + @Field("orderDate") Date date; + + @Field("quantity") Integer qty; + + } +} From f9f4c4621be4a8bd03a542caf82b48a528d913db Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 23 Aug 2021 11:16:21 +0200 Subject: [PATCH 0484/1381] Polishing. Update javadoc and add assertions. See #3711 Original pull request: #3739. --- .../aggregation/SetWindowFieldsOperation.java | 176 ++++++++++-------- .../SetWindowFieldsOperationTests.java | 2 + .../SetWindowFieldsOperationUnitTests.java | 4 +- 3 files changed, 107 insertions(+), 75 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java index 0f0909beb2..9c40a0b642 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java @@ -25,6 +25,8 @@ import org.springframework.util.Assert; /** + * Encapsulates the {@code setWindowFields}-operation. + * * @author Christoph Strobl * @since 3.3 * @see fields; + private final List fields; /** * Create a new output containing the single given {@link ComputedField field}. @@ -128,6 +129,7 @@ public static class WindowOutput { public WindowOutput(ComputedField outputField) { Assert.notNull(outputField, "OutputField must not be null!"); + this.fields = new ArrayList<>(); this.fields.add(outputField); } @@ -141,6 +143,7 @@ public WindowOutput(ComputedField outputField) { public WindowOutput append(ComputedField field) { Assert.notNull(field, "Field must not be null!"); + fields.add(field); return this; } @@ -202,11 +205,9 @@ interface ComputedFieldAppender { */ public static class ComputedField implements Field { - private String name; - private AggregationExpression windowOperator; - - @Nullable // - private Window window; + private final String name; + private final AggregationExpression windowOperator; + private final @Nullable Window window; /** * Create a new {@link ComputedField}. @@ -286,7 +287,7 @@ static DocumentWindow documents(Object lower, Object upper) { * @return new instance of {@link RangeWindow}. */ static RangeWindow range(Object lower, Object upper, @Nullable WindowUnit unit) { - return new RangeWindow(lower, upper, unit); + return new RangeWindow(lower, upper, unit == null ? WindowUnits.DEFAULT : unit); } /** @@ -314,18 +315,18 @@ static DocumentWindowBuilder documents() { public interface Window { /** - * The upper (inclusive) boundary. + * The lower (inclusive) boundary. * * @return */ - Object getUpper(); + Object getLower(); /** - * The lower (inclusive) boundary. - * + * The upper (inclusive) boundary. + * * @return */ - Object getLower(); + Object getUpper(); /** * Obtain the document representation of the window in a default {@link AggregationOperationContext context}. @@ -351,14 +352,21 @@ default Document toDocument() { */ public static class RangeWindowBuilder { - @Nullable // - private Object upper; + private @Nullable Object lower; + private @Nullable Object upper; + private @Nullable WindowUnit unit; - @Nullable // - private Object lower; + /** + * The lower (inclusive) range limit based on the sortBy field. + * + * @param lower eg. {@literal current} or {@literal unbounded}. + * @return this. + */ + public RangeWindowBuilder from(String lower) { - @Nullable // - private WindowUnit unit; + this.lower = lower; + return this; + } /** * The upper (inclusive) range limit based on the sortBy field. @@ -373,19 +381,23 @@ public RangeWindowBuilder to(String upper) { } /** - * The lower (inclusive) range limit based on the sortBy field. + * The lower (inclusive) range limit value to add to the value based on the sortBy field. Use a negative integer for + * a position before the current document. Use a positive integer for a position after the current document. + * {@code 0} is the current document position. * - * @param lower eg. {@literal current} or {@literal unbounded}. + * @param lower * @return this. */ - public RangeWindowBuilder from(String lower) { + public RangeWindowBuilder from(Number lower) { this.lower = lower; return this; } /** - * The upper (inclusive) range limit value to add to the value based on the sortBy field. + * The upper (inclusive) range limit value to add to the value based on the sortBy field. Use a negative integer for + * a position before the current document. Use a positive integer for a position after the current document. + * {@code 0} is the current document position. * * @param upper * @return this. @@ -396,25 +408,13 @@ public RangeWindowBuilder to(Number upper) { return this; } - /** - * The lower (inclusive) range limit value to add to the value based on the sortBy field. - * - * @param lower - * @return this. - */ - public RangeWindowBuilder from(Number lower) { - - this.lower = lower; - return this; - } - /** * Use {@literal current} as {@link #from(String) lower} limit. * * @return this. */ public RangeWindowBuilder fromCurrent() { - return from("current"); + return from(CURRENT); } /** @@ -423,7 +423,7 @@ public RangeWindowBuilder fromCurrent() { * @return this. */ public RangeWindowBuilder fromUnbounded() { - return from("unbounded"); + return from(UNBOUNDED); } /** @@ -432,7 +432,7 @@ public RangeWindowBuilder fromUnbounded() { * @return this. */ public RangeWindowBuilder toCurrent() { - return to("current"); + return to(CURRENT); } /** @@ -441,7 +441,7 @@ public RangeWindowBuilder toCurrent() { * @return this. */ public RangeWindowBuilder toUnbounded() { - return to("unbounded"); + return to(UNBOUNDED); } /** @@ -452,7 +452,8 @@ public RangeWindowBuilder toUnbounded() { */ public RangeWindowBuilder unit(WindowUnit windowUnit) { - this.unit = unit; + Assert.notNull(windowUnit, "WindowUnit must not be null"); + this.unit = windowUnit; return this; } @@ -462,6 +463,11 @@ public RangeWindowBuilder unit(WindowUnit windowUnit) { * @return new instance of {@link RangeWindow}. */ public RangeWindow build() { + + Assert.notNull(lower, "Lower bound must not be null"); + Assert.notNull(upper, "Upper bound must not be null"); + Assert.notNull(unit, "WindowUnit bound must not be null"); + return new RangeWindow(lower, upper, unit); } } @@ -473,12 +479,17 @@ public RangeWindow build() { */ public static class DocumentWindowBuilder { - @Nullable // - private Object upper; - - @Nullable // - private Object lower; + private @Nullable Object lower; + private @Nullable Object upper; + /** + * The lower (inclusive) range limit based on current document. Use a negative integer for a position before the + * current document. Use a positive integer for a position after the current document. {@code 0} is the current + * document position. + * + * @param lower + * @return this. + */ public DocumentWindowBuilder from(Number lower) { this.lower = lower; @@ -486,11 +497,11 @@ public DocumentWindowBuilder from(Number lower) { } public DocumentWindowBuilder fromCurrent() { - return from("current"); + return from(CURRENT); } public DocumentWindowBuilder fromUnbounded() { - return from("unbounded"); + return from(UNBOUNDED); } public DocumentWindowBuilder to(String upper) { @@ -512,9 +523,11 @@ public DocumentWindowBuilder from(String lower) { } /** - * The upper (inclusive) range limit based on current document. + * The upper (inclusive) range limit based on current document. Use a negative integer for a position before the + * current document. Use a positive integer for a position after the current document. {@code 0} is the current + * document position. * - * @param upper eg. {@literal current} or {@literal unbounded}. + * @param upper * @return this. */ public DocumentWindowBuilder to(Number upper) { @@ -524,14 +537,18 @@ public DocumentWindowBuilder to(Number upper) { } public DocumentWindowBuilder toCurrent() { - return to("current"); + return to(CURRENT); } public DocumentWindowBuilder toUnbounded() { - return to("unbounded"); + return to(UNBOUNDED); } public DocumentWindow build() { + + Assert.notNull(lower, "Lower bound must not be null"); + Assert.notNull(upper, "Upper bound must not be null"); + return new DocumentWindow(lower, upper); } } @@ -541,24 +558,24 @@ public DocumentWindow build() { * * @author Christoph Strobl */ - abstract static class WindowImp implements Window { + static abstract class WindowImpl implements Window { - private final Object upper; private final Object lower; + private final Object upper; - protected WindowImp(Object lower, Object upper) { - this.upper = upper; + protected WindowImpl(Object lower, Object upper) { this.lower = lower; + this.upper = upper; } @Override - public Object getUpper() { - return upper; + public Object getLower() { + return lower; } @Override - public Object getLower() { - return lower; + public Object getUpper() { + return upper; } } @@ -567,7 +584,7 @@ public Object getLower() { * * @author Christoph Strobl */ - public static class DocumentWindow extends WindowImp { + public static class DocumentWindow extends WindowImpl { DocumentWindow(Object lower, Object upper) { super(lower, upper); @@ -584,10 +601,9 @@ public Document toDocument(AggregationOperationContext ctx) { * * @author Christoph Strobl */ - public static class RangeWindow extends WindowImp { + public static class RangeWindow extends WindowImpl { - @Nullable // - private WindowUnit unit; + private final WindowUnit unit; protected RangeWindow(Object lower, Object upper, WindowUnit unit) { @@ -634,10 +650,12 @@ public static class SetWindowFieldsOperationBuilder { /** * Specify the field to group by. * - * @param fieldName must not be {@literal null}. + * @param fieldName must not be {@literal null} or null. * @return this. */ public SetWindowFieldsOperationBuilder partitionByField(String fieldName) { + + Assert.hasText(fieldName, "Field name must not be empty or null"); return partitionBy(Fields.field("$" + fieldName, fieldName)); } @@ -679,6 +697,8 @@ public SetWindowFieldsOperationBuilder sortBy(Sort sort) { */ public SetWindowFieldsOperationBuilder sortBy(SortOperation sort) { + Assert.notNull(sort, "SortOperation must not be null"); + this.sortOperation = sort; return this; } @@ -691,6 +711,8 @@ public SetWindowFieldsOperationBuilder sortBy(SortOperation sort) { */ public SetWindowFieldsOperationBuilder output(WindowOutput output) { + Assert.notNull(output, "WindowOutput must not be null"); + this.output = output; return this; } @@ -710,6 +732,8 @@ public WindowChoice output(AggregationExpression expression) { @Override public As within(Window window) { + Assert.notNull(window, "Window must not be null"); + this.window = window; return this; } @@ -717,6 +741,8 @@ public As within(Window window) { @Override public SetWindowFieldsOperationBuilder as(String targetFieldName) { + Assert.hasText(targetFieldName, "Target field name must not be empty or null"); + ComputedField computedField = new ComputedField(targetFieldName, expression, window); if (SetWindowFieldsOperationBuilder.this.output == null) { @@ -738,7 +764,7 @@ public interface As { /** * Define the target name field name to hold the computation result. * - * @param targetFieldName must not be {@literal null}. + * @param targetFieldName must not be {@literal null} or empty. * @return the starting point {@link SetWindowFieldsOperationBuilder builder} instance. */ SetWindowFieldsOperationBuilder as(String targetFieldName); @@ -760,20 +786,22 @@ public interface WindowChoice extends As { } /** - * Partition by a value that transaltes to a valid mongodb expression. + * Partition by a value that translates to a valid mongodb expression. * * @param value must not be {@literal null}. * @return this. */ public SetWindowFieldsOperationBuilder partitionBy(Object value) { + Assert.notNull(value, "Partition By must not be null"); + partitionBy = value; return this; } /** * Obtain a new instance of {@link SetWindowFieldsOperation} with previously set arguments. - * + * * @return new instance of {@link SetWindowFieldsOperation}. */ public SetWindowFieldsOperation build() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java index b88e0479a3..17bfb9b5a3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationTests.java @@ -37,6 +37,8 @@ import org.springframework.data.mongodb.test.util.Template; /** + * Integration tests for {@link SetWindowFieldsOperation}. + * * @author Christoph Strobl */ @ExtendWith(MongoTemplateExtension.class) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java index 87e3f8f54c..62b0f4dffc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperationUnitTests.java @@ -33,9 +33,11 @@ import org.springframework.lang.Nullable; /** + * Unit tests for {@link SetWindowFieldsOperation}. + * * @author Christoph Strobl */ -public class SetWindowFieldsOperationUnitTests { +class SetWindowFieldsOperationUnitTests { @Test // GH-3711 void rendersTargetFieldNamesCorrectly() { From c574e5cf8a5b553399a0faf65d1ba0e1574470aa Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 22 Jul 2021 11:44:15 +0200 Subject: [PATCH 0485/1381] Add support for `$covariancePop` and `$covarianceSamp` aggregation expressions. Closes: #3712 Original pull request: #3740. --- .../aggregation/AccumulatorOperators.java | 177 ++++++++++++++++++ .../core/aggregation/ArithmeticOperators.java | 59 ++++++ .../core/spel/MethodReferenceNode.java | 2 + .../aggregation/TestAggregationContext.java | 75 ++++++++ .../AccumulatorOperatorsUnitTests.java | 77 ++++++++ .../SpelExpressionTransformerUnitTests.java | 10 + 6 files changed, 400 insertions(+) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/aggregation/TestAggregationContext.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java index 6698b932f8..1ea1af9731 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java @@ -142,6 +142,63 @@ public StdDevSamp stdDevSamp() { return usesFieldRef() ? StdDevSamp.stdDevSampOf(fieldReference) : StdDevSamp.stdDevSampOf(expression); } + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given + * field to calculate the population covariance of the two. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovariancePop covariancePop(String fieldReference) { + return covariancePop().and(fieldReference); + } + + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given + * {@link AggregationExpression expression} to calculate the population covariance of the two. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovariancePop covariancePop(AggregationExpression expression) { + return covariancePop().and(expression); + } + + private CovariancePop covariancePop() { + return usesFieldRef() ? CovariancePop.covariancePopOf(fieldReference) : CovariancePop.covariancePopOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given + * field to calculate the sample covariance of the two. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovarianceSamp covarianceSamp(String fieldReference) { + return covarianceSamp().and(fieldReference); + } + + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given + * {@link AggregationExpression expression} to calculate the sample covariance of the two. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovarianceSamp covarianceSamp(AggregationExpression expression) { + return covarianceSamp().and(expression); + } + + private CovarianceSamp covarianceSamp() { + return usesFieldRef() ? CovarianceSamp.covarianceSampOf(fieldReference) + : CovarianceSamp.covarianceSampOf(expression); + } + private boolean usesFieldRef() { return fieldReference != null; } @@ -658,4 +715,124 @@ public Document toDocument(Object value, AggregationOperationContext context) { return super.toDocument(value, context); } } + + /** + * {@link AggregationExpression} for {@code $covariancePop}. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class CovariancePop extends AbstractAggregationExpression { + + private CovariancePop(Object value) { + super(value); + } + + /** + * Creates new {@link CovariancePop}. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + */ + public static CovariancePop covariancePopOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new CovariancePop(asFields(fieldReference)); + } + + /** + * Creates new {@link CovariancePop}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + */ + public static CovariancePop covariancePopOf(AggregationExpression expression) { + return new CovariancePop(Collections.singletonList(expression)); + } + + /** + * Creates new {@link CovariancePop} with all previously added arguments appending the given one. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + */ + public CovariancePop and(String fieldReference) { + return new CovariancePop(append(asFields(fieldReference))); + } + + /** + * Creates new {@link CovariancePop} with all previously added arguments appending the given one. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + */ + public CovariancePop and(AggregationExpression expression) { + return new CovariancePop(append(expression)); + } + + @Override + protected String getMongoMethod() { + return "$covariancePop"; + } + } + + /** + * {@link AggregationExpression} for {@code $covarianceSamp}. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class CovarianceSamp extends AbstractAggregationExpression { + + private CovarianceSamp(Object value) { + super(value); + } + + /** + * Creates new {@link CovarianceSamp}. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovarianceSamp}. + */ + public static CovarianceSamp covarianceSampOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new CovarianceSamp(asFields(fieldReference)); + } + + /** + * Creates new {@link CovarianceSamp}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovarianceSamp}. + */ + public static CovarianceSamp covarianceSampOf(AggregationExpression expression) { + return new CovarianceSamp(Collections.singletonList(expression)); + } + + /** + * Creates new {@link CovarianceSamp} with all previously added arguments appending the given one. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovarianceSamp}. + */ + public CovarianceSamp and(String fieldReference) { + return new CovarianceSamp(append(asFields(fieldReference))); + } + + /** + * Creates new {@link CovarianceSamp} with all previously added arguments appending the given one. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovarianceSamp}. + */ + public CovarianceSamp and(AggregationExpression expression) { + return new CovarianceSamp(append(expression)); + } + + @Override + protected String getMongoMethod() { + return "$covarianceSamp"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 6053f3ae1b..b27e54d298 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -19,6 +19,8 @@ import java.util.List; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Avg; +import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.CovariancePop; +import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.CovarianceSamp; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Max; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Min; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevPop; @@ -511,6 +513,63 @@ public StdDevSamp stdDevSamp() { : AccumulatorOperators.StdDevSamp.stdDevSampOf(expression); } + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given + * field to calculate the population covariance of the two. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovariancePop covariancePop(String fieldReference) { + return covariancePop().and(fieldReference); + } + + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given + * {@link AggregationExpression expression} to calculate the population covariance of the two. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovariancePop covariancePop(AggregationExpression expression) { + return covariancePop().and(expression); + } + + private CovariancePop covariancePop() { + return usesFieldRef() ? CovariancePop.covariancePopOf(fieldReference) : CovariancePop.covariancePopOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given + * field to calculate the sample covariance of the two. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovarianceSamp covarianceSamp(String fieldReference) { + return covarianceSamp().and(fieldReference); + } + + /** + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given + * {@link AggregationExpression expression} to calculate the sample covariance of the two. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link CovariancePop}. + * @since 3.3 + */ + public CovarianceSamp covarianceSamp(AggregationExpression expression) { + return covarianceSamp().and(expression); + } + + private CovarianceSamp covarianceSamp() { + return usesFieldRef() ? CovarianceSamp.covarianceSampOf(fieldReference) + : CovarianceSamp.covarianceSampOf(expression); + } + /** * Creates new {@link AggregationExpression} that rounds a number to a whole integer or to a specified decimal * place. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 5a2c48bc20..c858926446 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -170,6 +170,8 @@ public class MethodReferenceNode extends ExpressionNode { map.put("addToSet", singleArgRef().forOperator("$addToSet")); map.put("stdDevPop", arrayArgRef().forOperator("$stdDevPop")); map.put("stdDevSamp", arrayArgRef().forOperator("$stdDevSamp")); + map.put("covariancePop", arrayArgRef().forOperator("$covariancePop")); + map.put("covarianceSamp", arrayArgRef().forOperator("$covarianceSamp")); // TYPE OPERATORS map.put("type", singleArgRef().forOperator("$type")); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/aggregation/TestAggregationContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/aggregation/TestAggregationContext.java new file mode 100644 index 0000000000..4f16072e43 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/aggregation/TestAggregationContext.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021 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 + * + * https://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.util.aggregation; + +import org.bson.Document; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; +import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference; +import org.springframework.data.mongodb.core.aggregation.Field; +import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + */ +public class TestAggregationContext implements AggregationOperationContext { + + private final AggregationOperationContext delegate; + + private TestAggregationContext(AggregationOperationContext delegate) { + this.delegate = delegate; + } + + public static AggregationOperationContext contextFor(@Nullable Class type) { + + MappingMongoConverter mongoConverter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, + new MongoMappingContext()); + mongoConverter.afterPropertiesSet(); + + return contextFor(type, mongoConverter); + } + + public static AggregationOperationContext contextFor(@Nullable Class type, MongoConverter mongoConverter) { + + if (type == null) { + return Aggregation.DEFAULT_CONTEXT; + } + + return new TestAggregationContext(new TypeBasedAggregationOperationContext(type, mongoConverter.getMappingContext(), + new QueryMapper(mongoConverter)).continueOnMissingFieldReference()); + } + + @Override + public Document getMappedObject(Document document, @Nullable Class type) { + return delegate.getMappedObject(document, type); + } + + @Override + public FieldReference getReference(Field field) { + return delegate.getReference(field); + } + + @Override + public FieldReference getReference(String name) { + return delegate.getReference(name); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java new file mode 100644 index 0000000000..977183c448 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java @@ -0,0 +1,77 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Arrays; +import java.util.Date; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.aggregation.DateOperators.Year; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.util.aggregation.TestAggregationContext; + +/** + * @author Christoph Strobl + */ +class AccumulatorOperatorsUnitTests { + + @Test // GH-3712 + void rendersCovariancePopWithFieldReference() { + + assertThat(AccumulatorOperators.valueOf("balance").covariancePop("midichlorianCount") + .toDocument(TestAggregationContext.contextFor(Jedi.class))) + .isEqualTo(new Document("$covariancePop", Arrays.asList("$balance", "$force"))); + } + + @Test // GH-3712 + void rendersCovariancePopWithExpression() { + + assertThat(AccumulatorOperators.valueOf(Year.yearOf("birthdate")).covariancePop("midichlorianCount") + .toDocument(TestAggregationContext.contextFor(Jedi.class))) + .isEqualTo(new Document("$covariancePop", Arrays.asList(new Document("$year", "$birthdate"), "$force"))); + } + + @Test // GH-3712 + void rendersCovarianceSampWithFieldReference() { + + assertThat(AccumulatorOperators.valueOf("balance").covarianceSamp("midichlorianCount") + .toDocument(TestAggregationContext.contextFor(Jedi.class))) + .isEqualTo(new Document("$covarianceSamp", Arrays.asList("$balance", "$force"))); + } + + @Test // GH-3712 + void rendersCovarianceSampWithExpression() { + + assertThat(AccumulatorOperators.valueOf(Year.yearOf("birthdate")).covarianceSamp("midichlorianCount") + .toDocument(TestAggregationContext.contextFor(Jedi.class))) + .isEqualTo(new Document("$covarianceSamp", Arrays.asList(new Document("$year", "$birthdate"), "$force"))); + } + + static class Jedi { + + String name; + + Date birthdate; + + @Field("force") + Integer midichlorianCount; + + Integer balance; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index b67beed126..c4b945ab94 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -946,6 +946,16 @@ public void shouldRenderRoundWithPlace() { assertThat(transform("round(field, 2)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\", 2]}")); } + @Test // GH-3712 + void shouldRenderCovariancePop() { + assertThat(transform("covariancePop(field1, field2)")).isEqualTo(Document.parse("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}")); + } + + @Test // GH-3712 + void shouldRenderCovarianceSamp() { + assertThat(transform("covarianceSamp(field1, field2)")).isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From dbfd4e5c624a9770a2ee6d3235b1e22a604583c7 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 22 Jul 2021 11:44:15 +0200 Subject: [PATCH 0486/1381] Polishing. Reformat code. See #3712 Original pull request: #3740. --- .../core/aggregation/AccumulatorOperators.java | 16 ++++++++-------- .../AccumulatorOperatorsUnitTests.java | 2 ++ src/main/asciidoc/reference/mongodb.adoc | 8 ++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java index 1ea1af9731..13913caacf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java @@ -143,8 +143,8 @@ public StdDevSamp stdDevSamp() { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given - * field to calculate the population covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the + * given field to calculate the population covariance of the two. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -155,8 +155,8 @@ public CovariancePop covariancePop(String fieldReference) { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given - * {@link AggregationExpression expression} to calculate the population covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the + * given {@link AggregationExpression expression} to calculate the population covariance of the two. * * @param expression must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -171,8 +171,8 @@ private CovariancePop covariancePop() { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given - * field to calculate the sample covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the + * given field to calculate the sample covariance of the two. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -183,8 +183,8 @@ public CovarianceSamp covarianceSamp(String fieldReference) { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given - * {@link AggregationExpression expression} to calculate the sample covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the + * given {@link AggregationExpression expression} to calculate the sample covariance of the two. * * @param expression must not be {@literal null}. * @return new instance of {@link CovariancePop}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java index 977183c448..6948255d15 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java @@ -27,6 +27,8 @@ import org.springframework.data.mongodb.util.aggregation.TestAggregationContext; /** + * Unit tests for {@link AccumulatorOperators}. + * * @author Christoph Strobl */ class AccumulatorOperatorsUnitTests { diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 84afc7ea09..3bfa500731 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -1002,7 +1002,7 @@ assertThat(upserted.getFirstName()).isEqualTo("Mary"); assertThat(upserted.getAge()).isOne(); ---- -[[mongo-template.aggregation-update]] += [[mongo-template.aggregation-update]] === Aggregation Pipeline Updates Update methods exposed by `MongoOperations` and `ReactiveMongoOperations` also accept an <> via `AggregationUpdate`. @@ -2502,8 +2502,8 @@ At the time of this writing, we provide support for the following Aggregation Op | Set Aggregation Operators | `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue` -| Group Aggregation Operators -| `addToSet`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` +| Group/Accumulator Aggregation Operators +| `addToSet`, `covariancePop`, `covarianceSamp`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators | `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` @@ -2544,7 +2544,7 @@ At the time of this writing, we provide support for the following Aggregation Op * The operation is mapped or added by Spring Data MongoDB. -Note that the aggregation operations not listed here are currently not supported by Spring Data MongoDB. Comparison aggregation operators are expressed as `Criteria` expressions. +Note that the aggregation operations not listed here are currently not supported by Spring Data MongoDB.Comparison aggregation operators are expressed as `Criteria` expressions. [[mongo.aggregation.projection]] === Projection Expressions From f3e067f59f9147b4abc314b021c8b7769c2bc127 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 23 Jul 2021 09:10:35 +0200 Subject: [PATCH 0487/1381] Add support for `$expMovingAvg` aggregation operator. The SpEL support for this one is missing due to the differing argument map (N, alpha). Closes: #3718 Original pull request: #3744. --- .../aggregation/AccumulatorOperators.java | 111 ++++++++++++++++++ .../AccumulatorOperatorsUnitTests.java | 24 +++- src/main/asciidoc/reference/mongodb.adoc | 2 +- 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java index 13913caacf..ba2c34edab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperators.java @@ -199,11 +199,61 @@ private CovarianceSamp covarianceSamp() { : CovarianceSamp.covarianceSampOf(expression); } + /** + * Creates new {@link ExpMovingAvgBuilder} that to build {@link AggregationExpression expMovingAvg} that calculates + * the exponential moving average of numeric values + * + * @return new instance of {@link ExpMovingAvg}. + * @since 3.3 + */ + public ExpMovingAvgBuilder expMovingAvg() { + + ExpMovingAvg expMovingAvg = usesFieldRef() ? ExpMovingAvg.expMovingAvgOf(fieldReference) + : ExpMovingAvg.expMovingAvgOf(expression); + return new ExpMovingAvgBuilder() { + + @Override + public ExpMovingAvg historicalDocuments(int numberOfHistoricalDocuments) { + return expMovingAvg.n(numberOfHistoricalDocuments); + } + + @Override + public ExpMovingAvg alpha(double exponentialDecayValue) { + return expMovingAvg.alpha(exponentialDecayValue); + } + }; + } + private boolean usesFieldRef() { return fieldReference != null; } } + /** + * Builder for {@link ExpMovingAvg}. + * + * @since 3.3 + */ + public interface ExpMovingAvgBuilder { + + /** + * Define the number of historical documents with significant mathematical weight. + * + * @param numberOfHistoricalDocuments + * @return new instance of {@link ExpMovingAvg}. + */ + ExpMovingAvg historicalDocuments(int numberOfHistoricalDocuments); + + /** + * Define the exponential decay value. + * + * @param exponentialDecayValue + * @return new instance of {@link ExpMovingAvg}. + */ + ExpMovingAvg alpha(double exponentialDecayValue); + + } + /** * {@link AggregationExpression} for {@code $sum}. * @@ -835,4 +885,65 @@ protected String getMongoMethod() { return "$covarianceSamp"; } } + + /** + * {@link ExpMovingAvg} calculates the exponential moving average of numeric values. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class ExpMovingAvg extends AbstractAggregationExpression { + + private ExpMovingAvg(Object value) { + super(value); + } + + /** + * Create a new {@link ExpMovingAvg} by defining the field holding the value to be used as input. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link ExpMovingAvg}. + */ + public static ExpMovingAvg expMovingAvgOf(String fieldReference) { + return new ExpMovingAvg(Collections.singletonMap("input", Fields.field(fieldReference))); + } + + /** + * Create a new {@link ExpMovingAvg} by defining the {@link AggregationExpression expression} to compute the value + * to be used as input. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link ExpMovingAvg}. + */ + public static ExpMovingAvg expMovingAvgOf(AggregationExpression expression) { + return new ExpMovingAvg(Collections.singletonMap("input", expression)); + } + + /** + * Define the number of historical documents with significant mathematical weight.
      + * Specify either {@link #n(int) N} or {@link #alpha(double) aplha}. Not both! + * + * @param numberOfHistoricalDocuments + * @return new instance of {@link ExpMovingAvg}. + */ + public ExpMovingAvg n/*umber of historical documents*/(int numberOfHistoricalDocuments) { + return new ExpMovingAvg(append("N", numberOfHistoricalDocuments)); + } + + /** + * Define the exponential decay value.
      + * Specify either {@link #alpha(double) aplha} or {@link #n(int) N}. Not both! + * + * @param exponentialDecayValue + * @return new instance of {@link ExpMovingAvg}. + */ + public ExpMovingAvg alpha(double exponentialDecayValue) { + return new ExpMovingAvg(append("alpha", exponentialDecayValue)); + } + + @Override + protected String getMongoMethod() { + return "$expMovingAvg"; + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java index 6948255d15..27bd876255 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AccumulatorOperatorsUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.core.aggregation; import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.*; import java.util.Arrays; import java.util.Date; @@ -46,7 +47,7 @@ void rendersCovariancePopWithExpression() { assertThat(AccumulatorOperators.valueOf(Year.yearOf("birthdate")).covariancePop("midichlorianCount") .toDocument(TestAggregationContext.contextFor(Jedi.class))) - .isEqualTo(new Document("$covariancePop", Arrays.asList(new Document("$year", "$birthdate"), "$force"))); + .isEqualTo(new Document("$covariancePop", Arrays.asList(new Document("$year", "$birthdate"), "$force"))); } @Test // GH-3712 @@ -54,7 +55,7 @@ void rendersCovarianceSampWithFieldReference() { assertThat(AccumulatorOperators.valueOf("balance").covarianceSamp("midichlorianCount") .toDocument(TestAggregationContext.contextFor(Jedi.class))) - .isEqualTo(new Document("$covarianceSamp", Arrays.asList("$balance", "$force"))); + .isEqualTo(new Document("$covarianceSamp", Arrays.asList("$balance", "$force"))); } @Test // GH-3712 @@ -62,7 +63,21 @@ void rendersCovarianceSampWithExpression() { assertThat(AccumulatorOperators.valueOf(Year.yearOf("birthdate")).covarianceSamp("midichlorianCount") .toDocument(TestAggregationContext.contextFor(Jedi.class))) - .isEqualTo(new Document("$covarianceSamp", Arrays.asList(new Document("$year", "$birthdate"), "$force"))); + .isEqualTo(new Document("$covarianceSamp", Arrays.asList(new Document("$year", "$birthdate"), "$force"))); + } + + @Test // GH-3718 + void rendersExpMovingAvgWithNumberOfHistoricDocuments() { + + assertThat(valueOf("price").expMovingAvg().historicalDocuments(2).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $expMovingAvg: { input: \"$price\", N: 2 } }")); + } + + @Test // GH-3718 + void rendersExpMovingAvgWithAlpha() { + + assertThat(valueOf("price").expMovingAvg().alpha(0.75).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $expMovingAvg: { input: \"$price\", alpha: 0.75 } }")); } static class Jedi { @@ -71,8 +86,7 @@ static class Jedi { Date birthdate; - @Field("force") - Integer midichlorianCount; + @Field("force") Integer midichlorianCount; Integer balance; } diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 3bfa500731..dfa87dd3c7 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2503,7 +2503,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue` | Group/Accumulator Aggregation Operators -| `addToSet`, `covariancePop`, `covarianceSamp`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` +| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators | `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` From a977b8a790c0d71ad65e8a9bdab3ad6ca2005257 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 23 Aug 2021 13:26:57 +0200 Subject: [PATCH 0488/1381] Change visibility of Reactive/MongoRepositoryFactoryBean setters. Setters of the FactoryBean should be public. Closes: #3779 Original pull request: #3780. --- .../mongodb/repository/support/MongoRepositoryFactoryBean.java | 2 +- .../repository/support/ReactiveMongoRepositoryFactoryBean.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java index ade85d3110..8f156bdeea 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java @@ -70,7 +70,7 @@ public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#setMappingContext(org.springframework.data.mapping.context.MappingContext) */ @Override - protected void setMappingContext(MappingContext mappingContext) { + public void setMappingContext(MappingContext mappingContext) { super.setMappingContext(mappingContext); this.mappingContextConfigured = true; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java index 4e8232714f..6536983a70 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java @@ -80,7 +80,7 @@ public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#setMappingContext(org.springframework.data.mapping.context.MappingContext) */ @Override - protected void setMappingContext(MappingContext mappingContext) { + public void setMappingContext(MappingContext mappingContext) { super.setMappingContext(mappingContext); this.mappingContextConfigured = true; From 30da62181f92ee1e6983eccc4d017941e97ebbb8 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 22 Jul 2021 13:39:05 +0200 Subject: [PATCH 0489/1381] Add support for `$rank` and `$denseRank` aggregation operators. Closes: #3715 Original pull request: #3741. --- .../core/aggregation/DocumentOperators.java | 76 +++++++++++++++++++ .../SpelExpressionTransformer.java | 5 +- .../core/spel/MethodReferenceNode.java | 16 +++- .../DocumentOperatorsUnitTests.java | 39 ++++++++++ .../SpelExpressionTransformerUnitTests.java | 10 +++ 5 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java new file mode 100644 index 0000000000..8ba7acc5b8 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java @@ -0,0 +1,76 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import org.bson.Document; + +/** + * @author Christoph Strobl + * @since 3.3 + */ +public class DocumentOperators { + + /** + * Obtain the document position (including gaps) relative to others (rank). + * + * @return new instance of {@link Rank}. + * @since 3.3 + */ + public static Rank rank() { + return new Rank(); + } + + /** + * Obtain the document position (without gaps) relative to others (rank). + * + * @return new instance of {@link DenseRank}. + * @since 3.3 + */ + public static DenseRank denseRank() { + return new DenseRank(); + } + + /** + * {@link Rank} resolves the current document position (the rank) relative to other documents. If multiple documents + * occupy the same rank, {@literal $rank} places the document with the subsequent value at a rank with a gap. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Rank implements AggregationExpression { + + @Override + public Document toDocument(AggregationOperationContext context) { + return new Document("$rank", new Document()); + } + } + + /** + * {@link DenseRank} resolves the current document position (the rank) relative to other documents. If multiple + * documents occupy the same rank, {@literal $denseRank} places the document with the subsequent value at the next rank without + * any gaps. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class DenseRank implements AggregationExpression { + + @Override + public Document toDocument(AggregationOperationContext context) { + return new Document("$denseRank", new Document()); + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java index 33b5c72c78..e00740945b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java @@ -500,7 +500,10 @@ protected Object convert(AggregationExpressionTransformationContext argList = new ArrayList(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index c858926446..763ae830e5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -68,6 +68,10 @@ public class MethodReferenceNode extends ExpressionNode { map.put("lte", arrayArgRef().forOperator("$lte")); map.put("ne", arrayArgRef().forOperator("$ne")); + // DOCUMENT OPERATORS + map.put("rank", emptyRef().forOperator("$rank")); + map.put("denseRank", emptyRef().forOperator("$denseRank")); + // ARITHMETIC OPERATORS map.put("abs", singleArgRef().forOperator("$abs")); map.put("add", arrayArgRef().forOperator("$add")); @@ -307,6 +311,16 @@ static AggregationMethodReference mapArgRef() { return new AggregationMethodReference(null, ArgumentType.MAP, null); } + /** + * Create a new {@link AggregationMethodReference} for a {@link ArgumentType#EMPTY_DOCUMENT} argument. + * + * @return never {@literal null}. + * @since 3.3 + */ + static AggregationMethodReference emptyRef() { + return new AggregationMethodReference(null, ArgumentType.EMPTY_DOCUMENT, null); + } + /** * Create a new {@link AggregationMethodReference} for a given {@literal aggregationExpressionOperator} reusing * previously set arguments. @@ -342,7 +356,7 @@ AggregationMethodReference mappingParametersTo(String... aggregationExpressionPr * @since 1.10 */ public enum ArgumentType { - SINGLE, ARRAY, MAP + SINGLE, ARRAY, MAP, EMPTY_DOCUMENT } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java new file mode 100644 index 0000000000..27ac1beccd --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.aggregation.DocumentOperators.*; + +import org.bson.Document; +import org.junit.jupiter.api.Test; + +/** + * @author Christoph Strobl + */ +class DocumentOperatorsUnitTests { + + @Test // GH-3715 + void rendersRank() { + assertThat(rank().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$rank", new Document())); + } + + @Test // GH-3715 + void rendersDenseRank() { + assertThat(denseRank().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(new Document("$denseRank", new Document())); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index c4b945ab94..06659820d8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -956,6 +956,16 @@ void shouldRenderCovarianceSamp() { assertThat(transform("covarianceSamp(field1, field2)")).isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}")); } + @Test // GH-3715 + void shouldRenderRank() { + assertThat(transform("rank()")).isEqualTo(Document.parse("{ $rank : {} }")); + } + + @Test // GH-3715 + void shouldRenderDenseRank() { + assertThat(transform("denseRank()")).isEqualTo(Document.parse("{ $denseRank : {} }")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From 1a86761e2e2002ad4f0aee50de6ebabaa931c84c Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 22 Jul 2021 14:43:48 +0200 Subject: [PATCH 0490/1381] Add support for `$documentNumber` aggregation operator. Closes: #3717 Original pull request: #3741. --- .../core/aggregation/DocumentOperators.java | 26 +++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 1 + .../DocumentOperatorsUnitTests.java | 5 ++++ .../SpelExpressionTransformerUnitTests.java | 5 ++++ 4 files changed, 37 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java index 8ba7acc5b8..7a5918e047 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java @@ -18,6 +18,8 @@ import org.bson.Document; /** + * Gateway to {@literal document expressions} such as {@literal $rank, $documentNumber, etc.} + * * @author Christoph Strobl * @since 3.3 */ @@ -43,6 +45,16 @@ public static DenseRank denseRank() { return new DenseRank(); } + /** + * Obtain the current document position. + * + * @return new instance of {@link DocumentNumber}. + * @since 3.3 + */ + public static DocumentNumber documentNumber() { + return new DocumentNumber(); + } + /** * {@link Rank} resolves the current document position (the rank) relative to other documents. If multiple documents * occupy the same rank, {@literal $rank} places the document with the subsequent value at a rank with a gap. @@ -73,4 +85,18 @@ public Document toDocument(AggregationOperationContext context) { return new Document("$denseRank", new Document()); } } + + /** + * {@link DocumentNumber} resolves the current document position. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class DocumentNumber implements AggregationExpression { + + @Override + public Document toDocument(AggregationOperationContext context) { + return new Document("$documentNumber", new Document()); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 763ae830e5..a184c49be8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -71,6 +71,7 @@ public class MethodReferenceNode extends ExpressionNode { // DOCUMENT OPERATORS map.put("rank", emptyRef().forOperator("$rank")); map.put("denseRank", emptyRef().forOperator("$denseRank")); + map.put("documentNumber", emptyRef().forOperator("$documentNumber")); // ARITHMETIC OPERATORS map.put("abs", singleArgRef().forOperator("$abs")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java index 27ac1beccd..c6604bc543 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java @@ -36,4 +36,9 @@ void rendersDenseRank() { assertThat(denseRank().toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(new Document("$denseRank", new Document())); } + + @Test // GH-3717 + void rendersDocumentNumber() { + assertThat(documentNumber().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$documentNumber", new Document())); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 06659820d8..3c20b58d58 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -966,6 +966,11 @@ void shouldRenderDenseRank() { assertThat(transform("denseRank()")).isEqualTo(Document.parse("{ $denseRank : {} }")); } + @Test // GH-3717 + void shouldRenderDocumentNumber() { + assertThat(transform("documentNumber()")).isEqualTo(Document.parse("{ $documentNumber : {} }")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From 510028a834ff585e8805774a717bf94c56d009d8 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 23 Jul 2021 11:33:07 +0200 Subject: [PATCH 0491/1381] Add support for `$shift` aggregation Operator. Closes: #3727 Original pull request: #3741. --- .../core/aggregation/DocumentOperators.java | 124 +++++++++++++++++- .../core/spel/MethodReferenceNode.java | 1 + .../DocumentOperatorsUnitTests.java | 17 ++- .../SpelExpressionTransformerUnitTests.java | 14 ++ 4 files changed, 153 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java index 7a5918e047..76fa591e45 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.aggregation; +import java.util.Collections; + import org.bson.Document; /** @@ -45,6 +47,26 @@ public static DenseRank denseRank() { return new DenseRank(); } + /** + * Take the field referenced by given {@literal fieldReference}. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link DocumentOperatorsFactory}. + */ + public static DocumentOperatorsFactory valueOf(String fieldReference) { + return new DocumentOperatorsFactory(fieldReference); + } + + /** + * Take the value resulting from the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link DocumentOperatorsFactory}. + */ + public static DocumentOperatorsFactory valueOf(AggregationExpression expression) { + return new DocumentOperatorsFactory(expression); + } + /** * Obtain the current document position. * @@ -55,6 +77,35 @@ public static DocumentNumber documentNumber() { return new DocumentNumber(); } + /** + * @author Christoph Strobl + */ + public static class DocumentOperatorsFactory { + + private Object target; + + public DocumentOperatorsFactory(Object target) { + this.target = target; + } + + /** + * Creates new {@link AggregationExpression} that applies the expression to a document at specified position + * relative to the current document. + * + * @param by the value to add to the current position. + * @return new instance of {@link Shift}. + */ + public Shift shift(int by) { + + Shift shift = usesExpression() ? Shift.shift((AggregationExpression) target) : Shift.shift(target.toString()); + return shift.by(by); + } + + private boolean usesExpression() { + return target instanceof AggregationExpression; + } + } + /** * {@link Rank} resolves the current document position (the rank) relative to other documents. If multiple documents * occupy the same rank, {@literal $rank} places the document with the subsequent value at a rank with a gap. @@ -72,8 +123,8 @@ public Document toDocument(AggregationOperationContext context) { /** * {@link DenseRank} resolves the current document position (the rank) relative to other documents. If multiple - * documents occupy the same rank, {@literal $denseRank} places the document with the subsequent value at the next rank without - * any gaps. + * documents occupy the same rank, {@literal $denseRank} places the document with the subsequent value at the next + * rank without any gaps. * * @author Christoph Strobl * @since 3.3 @@ -99,4 +150,73 @@ public Document toDocument(AggregationOperationContext context) { return new Document("$documentNumber", new Document()); } } + + /** + * Shift applies an expression to a document in a specified position relative to the current document. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Shift extends AbstractAggregationExpression { + + private Shift(Object value) { + super(value); + } + + /** + * Specifies the field to evaluate and return. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Shift}. + */ + public static Shift shift(String fieldReference) { + return new Shift(Collections.singletonMap("output", Fields.field(fieldReference))); + } + + /** + * Specifies the {@link AggregationExpression expression} to evaluate and return. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Shift}. + */ + public static Shift shift(AggregationExpression expression) { + return new Shift(Collections.singletonMap("output", expression)); + } + + /** + * Shift the document position relative to the current. Use a positive value for follow up documents (eg. 1 for the + * next) or a negative value for the predecessor documents (eg. -1 for the previous). + * + * @param shiftBy value to add to the current position. + * @return new instance of {@link Shift}. + */ + public Shift by(int shiftBy) { + return new Shift(append("by", shiftBy)); + } + + /** + * Define the default value if the target document is out of range. + * + * @param value must not be {@literal null}. + * @return new instance of {@link Shift}. + */ + public Shift defaultTo(Object value) { + return new Shift(append("default", value)); + } + + /** + * Define the {@link AggregationExpression expression} to evaluate if the target document is out of range. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Shift}. + */ + public Shift defaultToValueOf(AggregationExpression expression) { + return defaultTo(expression); + } + + @Override + protected String getMongoMethod() { + return "$shift"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index a184c49be8..4052b2cbaa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -72,6 +72,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("rank", emptyRef().forOperator("$rank")); map.put("denseRank", emptyRef().forOperator("$denseRank")); map.put("documentNumber", emptyRef().forOperator("$documentNumber")); + map.put("shift", mapArgRef().forOperator("$shift").mappingParametersTo("output", "by", "default")); // ARITHMETIC OPERATORS map.put("abs", singleArgRef().forOperator("$abs")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java index c6604bc543..4a29db60df 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java @@ -39,6 +39,21 @@ void rendersDenseRank() { @Test // GH-3717 void rendersDocumentNumber() { - assertThat(documentNumber().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$documentNumber", new Document())); + assertThat(documentNumber().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(new Document("$documentNumber", new Document())); + } + + @Test // GH-3727 + void rendersShift() { + + assertThat(valueOf("quantity").shift(1).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1 } }")); + } + + @Test // GH-3727 + void rendersShiftWithDefault() { + + assertThat(valueOf("quantity").shift(1).defaultTo("Not available").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }")); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 3c20b58d58..334825a829 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -971,6 +971,20 @@ void shouldRenderDocumentNumber() { assertThat(transform("documentNumber()")).isEqualTo(Document.parse("{ $documentNumber : {} }")); } + @Test // GH-3727 + void rendersShift() { + + assertThat(transform("shift(quantity, 1)")) + .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1 } }")); + } + + @Test // GH-3727 + void rendersShiftWithDefault() { + + assertThat(transform("shift(quantity, 1, 'Not available')")) + .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From c8a791d36769e9fdd09568def1cce8c2bd524b70 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 10:59:06 +0200 Subject: [PATCH 0492/1381] Polishing. Make fields final where possible. Update javadoc. Simplify assertions. Update reference docs. See: #3715, See #3717, See #3727 Original pull request: #3741. --- .../core/aggregation/DocumentOperators.java | 2 +- .../SpelExpressionTransformer.java | 2 +- .../core/spel/ExpressionTransformer.java | 2 +- .../DocumentOperatorsUnitTests.java | 15 +- .../SpelExpressionTransformerUnitTests.java | 546 +++++++++--------- src/main/asciidoc/reference/mongodb.adoc | 7 +- 6 files changed, 291 insertions(+), 283 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java index 76fa591e45..40e0065a66 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java @@ -82,7 +82,7 @@ public static DocumentNumber documentNumber() { */ public static class DocumentOperatorsFactory { - private Object target; + private final Object target; public DocumentOperatorsFactory(Object target) { this.target = target; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java index e00740945b..f47e062238 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformer.java @@ -102,7 +102,7 @@ public Object transform(String expression, AggregationOperationContext context, ExpressionState state = new ExpressionState(new StandardEvaluationContext(params), CONFIG); ExpressionNode node = ExpressionNode.from(spelExpression.getAST(), state); - return transform(new AggregationExpressionTransformationContext(node, null, null, context)); + return transform(new AggregationExpressionTransformationContext<>(node, null, null, context)); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java index d35ed2800a..3f3b405cc6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/ExpressionTransformer.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.core.spel; /** - * SPI interface to implement components that can transfrom an {@link ExpressionTransformationContextSupport} into an + * SPI interface to implement components that can transform an {@link ExpressionTransformationContextSupport} into an * object. * * @author Oliver Gierke diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java index 4a29db60df..5cd0d4271e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DocumentOperatorsUnitTests.java @@ -15,45 +15,46 @@ */ package org.springframework.data.mongodb.core.aggregation; -import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.aggregation.DocumentOperators.*; +import static org.springframework.data.mongodb.test.util.Assertions.*; -import org.bson.Document; import org.junit.jupiter.api.Test; /** + * Unit tests for {@link DocumentOperators}. + * * @author Christoph Strobl */ class DocumentOperatorsUnitTests { @Test // GH-3715 void rendersRank() { - assertThat(rank().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$rank", new Document())); + assertThat(rank().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $rank: { } }"); } @Test // GH-3715 void rendersDenseRank() { assertThat(denseRank().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(new Document("$denseRank", new Document())); + .isEqualTo("{ $denseRank: { } }"); } @Test // GH-3717 void rendersDocumentNumber() { assertThat(documentNumber().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(new Document("$documentNumber", new Document())); + .isEqualTo("{ $documentNumber: { } }"); } @Test // GH-3727 void rendersShift() { assertThat(valueOf("quantity").shift(1).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1 } }")); + .isEqualTo("{ $shift: { output: \"$quantity\", by: 1 } }"); } @Test // GH-3727 void rendersShiftWithDefault() { assertThat(valueOf("quantity").shift(1).defaultTo("Not available").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }")); + .isEqualTo("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }"); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 334825a829..ee55818018 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.Person; +import org.springframework.lang.Nullable; /** * Unit tests for {@link SpelExpressionTransformer}. @@ -34,12 +35,12 @@ */ public class SpelExpressionTransformerUnitTests { - SpelExpressionTransformer transformer = new SpelExpressionTransformer(); + private SpelExpressionTransformer transformer = new SpelExpressionTransformer(); - Data data; + private Data data; @BeforeEach - public void beforeEach() { + void beforeEach() { this.data = new Data(); this.data.primitiveLongValue = 42; @@ -50,118 +51,118 @@ public void beforeEach() { } @Test // DATAMONGO-774 - public void shouldRenderConstantExpression() { + void shouldRenderConstantExpression() { - assertThat(transform("1")).isEqualTo((Object) "1"); - assertThat(transform("-1")).isEqualTo((Object) "-1"); - assertThat(transform("1.0")).isEqualTo((Object) "1.0"); - assertThat(transform("-1.0")).isEqualTo((Object) "-1.0"); + assertThat(transform("1")).isEqualTo("1"); + assertThat(transform("-1")).isEqualTo("-1"); + assertThat(transform("1.0")).isEqualTo("1.0"); + assertThat(transform("-1.0")).isEqualTo("-1.0"); assertThat(transform("null")).isNull(); } @Test // DATAMONGO-774 - public void shouldSupportKnownOperands() { + void shouldSupportKnownOperands() { - assertThat(transform("a + b")).isEqualTo((Object) Document.parse("{ \"$add\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a - b")).isEqualTo((Object) Document.parse("{ \"$subtract\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a * b")).isEqualTo((Object) Document.parse("{ \"$multiply\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a / b")).isEqualTo((Object) Document.parse("{ \"$divide\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a % b")).isEqualTo((Object) Document.parse("{ \"$mod\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("a + b")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("a - b")).isEqualTo(Document.parse("{ \"$subtract\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("a * b")).isEqualTo(Document.parse("{ \"$multiply\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("a / b")).isEqualTo(Document.parse("{ \"$divide\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("a % b")).isEqualTo(Document.parse("{ \"$mod\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-774 - public void shouldThrowExceptionOnUnknownOperand() { + void shouldThrowExceptionOnUnknownOperand() { assertThatIllegalArgumentException().isThrownBy(() -> transform("a++")); } @Test // DATAMONGO-774 - public void shouldRenderSumExpression() { - assertThat(transform("a + 1")).isEqualTo((Object) Document.parse("{ \"$add\" : [ \"$a\" , 1]}")); + void shouldRenderSumExpression() { + assertThat(transform("a + 1")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a\" , 1]}")); } @Test // DATAMONGO-774 - public void shouldRenderFormula() { + void shouldRenderFormula() { - assertThat(transform("(netPrice + surCharge) * taxrate + 42")).isEqualTo((Object) Document.parse( + assertThat(transform("(netPrice + surCharge) * taxrate + 42")).isEqualTo(Document.parse( "{ \"$add\" : [ { \"$multiply\" : [ { \"$add\" : [ \"$netPrice\" , \"$surCharge\"]} , \"$taxrate\"]} , 42]}")); } @Test // DATAMONGO-774 - public void shouldRenderFormulaInCurlyBrackets() { + void shouldRenderFormulaInCurlyBrackets() { - assertThat(transform("{(netPrice + surCharge) * taxrate + 42}")).isEqualTo((Object) Document.parse( + assertThat(transform("{(netPrice + surCharge) * taxrate + 42}")).isEqualTo(Document.parse( "{ \"$add\" : [ { \"$multiply\" : [ { \"$add\" : [ \"$netPrice\" , \"$surCharge\"]} , \"$taxrate\"]} , 42]}")); } @Test // DATAMONGO-774 - public void shouldRenderFieldReference() { + void shouldRenderFieldReference() { - assertThat(transform("foo")).isEqualTo((Object) "$foo"); - assertThat(transform("$foo")).isEqualTo((Object) "$foo"); + assertThat(transform("foo")).isEqualTo("$foo"); + assertThat(transform("$foo")).isEqualTo("$foo"); } @Test // DATAMONGO-774 - public void shouldRenderNestedFieldReference() { + void shouldRenderNestedFieldReference() { - assertThat(transform("foo.bar")).isEqualTo((Object) "$foo.bar"); - assertThat(transform("$foo.bar")).isEqualTo((Object) "$foo.bar"); + assertThat(transform("foo.bar")).isEqualTo("$foo.bar"); + assertThat(transform("$foo.bar")).isEqualTo("$foo.bar"); } @Test // DATAMONGO-774 @Disabled - public void shouldRenderNestedIndexedFieldReference() { + void shouldRenderNestedIndexedFieldReference() { // TODO add support for rendering nested indexed field references - assertThat(transform("foo[3].bar")).isEqualTo((Object) "$foo[3].bar"); + assertThat(transform("foo[3].bar")).isEqualTo("$foo[3].bar"); } @Test // DATAMONGO-774 - public void shouldRenderConsecutiveOperation() { - assertThat(transform("1 + 1 + 1")).isEqualTo((Object) Document.parse("{ \"$add\" : [ 1 , 1 , 1]}")); + void shouldRenderConsecutiveOperation() { + assertThat(transform("1 + 1 + 1")).isEqualTo(Document.parse("{ \"$add\" : [ 1 , 1 , 1]}")); } @Test // DATAMONGO-774 - public void shouldRenderComplexExpression0() { + void shouldRenderComplexExpression0() { assertThat(transform("-(1 + q)")) - .isEqualTo((Object) Document.parse("{ \"$multiply\" : [ -1 , { \"$add\" : [ 1 , \"$q\"]}]}")); + .isEqualTo(Document.parse("{ \"$multiply\" : [ -1 , { \"$add\" : [ 1 , \"$q\"]}]}")); } @Test // DATAMONGO-774 - public void shouldRenderComplexExpression1() { + void shouldRenderComplexExpression1() { - assertThat(transform("1 + (q + 1) / (q - 1)")).isEqualTo((Object) Document.parse( + assertThat(transform("1 + (q + 1) / (q - 1)")).isEqualTo(Document.parse( "{ \"$add\" : [ 1 , { \"$divide\" : [ { \"$add\" : [ \"$q\" , 1]} , { \"$subtract\" : [ \"$q\" , 1]}]}]}")); } @Test // DATAMONGO-774 - public void shouldRenderComplexExpression2() { + void shouldRenderComplexExpression2() { - assertThat(transform("(q + 1 + 4 - 5) / (q + 1 + 3 + 4)")).isEqualTo((Object) Document.parse( + assertThat(transform("(q + 1 + 4 - 5) / (q + 1 + 3 + 4)")).isEqualTo(Document.parse( "{ \"$divide\" : [ { \"$subtract\" : [ { \"$add\" : [ \"$q\" , 1 , 4]} , 5]} , { \"$add\" : [ \"$q\" , 1 , 3 , 4]}]}")); } @Test // DATAMONGO-774 - public void shouldRenderBinaryExpressionWithMixedSignsCorrectly() { + void shouldRenderBinaryExpressionWithMixedSignsCorrectly() { - assertThat(transform("-4 + 1")).isEqualTo((Object) Document.parse("{ \"$add\" : [ -4 , 1]}")); - assertThat(transform("1 + -4")).isEqualTo((Object) Document.parse("{ \"$add\" : [ 1 , -4]}")); + assertThat(transform("-4 + 1")).isEqualTo(Document.parse("{ \"$add\" : [ -4 , 1]}")); + assertThat(transform("1 + -4")).isEqualTo(Document.parse("{ \"$add\" : [ 1 , -4]}")); } @Test // DATAMONGO-774 - public void shouldRenderConsecutiveOperationsInComplexExpression() { + void shouldRenderConsecutiveOperationsInComplexExpression() { assertThat(transform("1 + 1 + (1 + 1 + 1) / q")).isEqualTo( - (Object) Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}")); + Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}")); } @Test // DATAMONGO-774 - public void shouldRenderParameterExpressionResults() { - assertThat(transform("[0] + [1] + [2]", 1, 2, 3)).isEqualTo((Object) Document.parse("{ \"$add\" : [ 1 , 2 , 3]}")); + void shouldRenderParameterExpressionResults() { + assertThat(transform("[0] + [1] + [2]", 1, 2, 3)).isEqualTo(Document.parse("{ \"$add\" : [ 1 , 2 , 3]}")); } @Test // DATAMONGO-774 - public void shouldRenderNestedParameterExpressionResults() { + void shouldRenderNestedParameterExpressionResults() { assertThat( ((Document) transform("[0].primitiveLongValue + [0].primitiveDoubleValue + [0].doubleValue.longValue()", data)) @@ -171,7 +172,7 @@ public void shouldRenderNestedParameterExpressionResults() { } @Test // DATAMONGO-774 - public void shouldRenderNestedParameterExpressionResultsInNestedExpressions() { + void shouldRenderNestedParameterExpressionResultsInNestedExpressions() { Document target = ((Document) transform( "((1 + [0].primitiveLongValue) + [0].primitiveDoubleValue) * [0].doubleValue.longValue()", data)); @@ -184,765 +185,767 @@ public void shouldRenderNestedParameterExpressionResultsInNestedExpressions() { } @Test // DATAMONGO-840 - public void shouldRenderCompoundExpressionsWithIndexerAndFieldReference() { + void shouldRenderCompoundExpressionsWithIndexerAndFieldReference() { Person person = new Person(); person.setAge(10); assertThat(transform("[0].age + a.c", person)) - .isEqualTo((Object) Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }")); + .isEqualTo(Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }")); } @Test // DATAMONGO-840 - public void shouldRenderCompoundExpressionsWithOnlyFieldReferences() { + void shouldRenderCompoundExpressionsWithOnlyFieldReferences() { - assertThat(transform("a.b + a.c")).isEqualTo((Object) Document.parse("{ \"$add\" : [ \"$a.b\" , \"$a.c\"]}")); + assertThat(transform("a.b + a.c")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a.b\" , \"$a.c\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeAnd() { - assertThat(transform("and(a, b)")).isEqualTo((Object) Document.parse("{ \"$and\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeAnd() { + assertThat(transform("and(a, b)")).isEqualTo(Document.parse("{ \"$and\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeOr() { - assertThat(transform("or(a, b)")).isEqualTo((Object) Document.parse("{ \"$or\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeOr() { + assertThat(transform("or(a, b)")).isEqualTo(Document.parse("{ \"$or\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeNot() { - assertThat(transform("not(a)")).isEqualTo((Object) Document.parse("{ \"$not\" : [ \"$a\"]}")); + void shouldRenderMethodReferenceNodeNot() { + assertThat(transform("not(a)")).isEqualTo(Document.parse("{ \"$not\" : [ \"$a\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSetEquals() { + void shouldRenderMethodReferenceNodeSetEquals() { assertThat(transform("setEquals(a, b)")) - .isEqualTo((Object) Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}")); + .isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSetEqualsForArrays() { + void shouldRenderMethodReferenceNodeSetEqualsForArrays() { assertThat(transform("setEquals(new int[]{1,2,3}, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$setEquals\" : [ [ 1 , 2 , 3] , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$setEquals\" : [ [ 1 , 2 , 3] , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSetEqualsMixedArrays() { + void shouldRenderMethodReferenceNodeSetEqualsMixedArrays() { assertThat(transform("setEquals(a, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$setEquals\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceSetIntersection() { + void shouldRenderMethodReferenceSetIntersection() { assertThat(transform("setIntersection(a, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$setIntersection\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$setIntersection\" : [ \"$a\" , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceSetUnion() { + void shouldRenderMethodReferenceSetUnion() { assertThat(transform("setUnion(a, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$setUnion\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$setUnion\" : [ \"$a\" , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceSeDifference() { + void shouldRenderMethodReferenceSeDifference() { assertThat(transform("setDifference(a, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$setDifference\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$setDifference\" : [ \"$a\" , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceSetIsSubset() { + void shouldRenderMethodReferenceSetIsSubset() { assertThat(transform("setIsSubset(a, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$setIsSubset\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$setIsSubset\" : [ \"$a\" , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceAnyElementTrue() { - assertThat(transform("anyElementTrue(a)")).isEqualTo((Object) Document.parse("{ \"$anyElementTrue\" : [ \"$a\"]}")); + void shouldRenderMethodReferenceAnyElementTrue() { + assertThat(transform("anyElementTrue(a)")).isEqualTo(Document.parse("{ \"$anyElementTrue\" : [ \"$a\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceAllElementsTrue() { + void shouldRenderMethodReferenceAllElementsTrue() { assertThat(transform("allElementsTrue(a, new int[]{4,5,6})")) - .isEqualTo((Object) Document.parse("{ \"$allElementsTrue\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo(Document.parse("{ \"$allElementsTrue\" : [ \"$a\" , [ 4 , 5 , 6]]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceCmp() { - assertThat(transform("cmp(a, 250)")).isEqualTo((Object) Document.parse("{ \"$cmp\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceCmp() { + assertThat(transform("cmp(a, 250)")).isEqualTo(Document.parse("{ \"$cmp\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceEq() { - assertThat(transform("eq(a, 250)")).isEqualTo((Object) Document.parse("{ \"$eq\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceEq() { + assertThat(transform("eq(a, 250)")).isEqualTo(Document.parse("{ \"$eq\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceGt() { - assertThat(transform("gt(a, 250)")).isEqualTo((Object) Document.parse("{ \"$gt\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceGt() { + assertThat(transform("gt(a, 250)")).isEqualTo(Document.parse("{ \"$gt\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceGte() { - assertThat(transform("gte(a, 250)")).isEqualTo((Object) Document.parse("{ \"$gte\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceGte() { + assertThat(transform("gte(a, 250)")).isEqualTo(Document.parse("{ \"$gte\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLt() { - assertThat(transform("lt(a, 250)")).isEqualTo((Object) Document.parse("{ \"$lt\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceLt() { + assertThat(transform("lt(a, 250)")).isEqualTo(Document.parse("{ \"$lt\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLte() { - assertThat(transform("lte(a, 250)")).isEqualTo((Object) Document.parse("{ \"$lte\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceLte() { + assertThat(transform("lte(a, 250)")).isEqualTo(Document.parse("{ \"$lte\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNe() { - assertThat(transform("ne(a, 250)")).isEqualTo((Object) Document.parse("{ \"$ne\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceNe() { + assertThat(transform("ne(a, 250)")).isEqualTo(Document.parse("{ \"$ne\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceAbs() { - assertThat(transform("abs(1)")).isEqualTo((Object) Document.parse("{ \"$abs\" : 1}")); + void shouldRenderMethodReferenceAbs() { + assertThat(transform("abs(1)")).isEqualTo(Document.parse("{ \"$abs\" : 1}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceAdd() { - assertThat(transform("add(a, 250)")).isEqualTo((Object) Document.parse("{ \"$add\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceAdd() { + assertThat(transform("add(a, 250)")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceCeil() { - assertThat(transform("ceil(7.8)")).isEqualTo((Object) Document.parse("{ \"$ceil\" : 7.8}")); + void shouldRenderMethodReferenceCeil() { + assertThat(transform("ceil(7.8)")).isEqualTo(Document.parse("{ \"$ceil\" : 7.8}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceDivide() { - assertThat(transform("divide(a, 250)")).isEqualTo((Object) Document.parse("{ \"$divide\" : [ \"$a\" , 250]}")); + void shouldRenderMethodReferenceDivide() { + assertThat(transform("divide(a, 250)")).isEqualTo(Document.parse("{ \"$divide\" : [ \"$a\" , 250]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceExp() { - assertThat(transform("exp(2)")).isEqualTo((Object) Document.parse("{ \"$exp\" : 2}")); + void shouldRenderMethodReferenceExp() { + assertThat(transform("exp(2)")).isEqualTo(Document.parse("{ \"$exp\" : 2}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceFloor() { - assertThat(transform("floor(2)")).isEqualTo((Object) Document.parse("{ \"$floor\" : 2}")); + void shouldRenderMethodReferenceFloor() { + assertThat(transform("floor(2)")).isEqualTo(Document.parse("{ \"$floor\" : 2}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLn() { - assertThat(transform("ln(2)")).isEqualTo((Object) Document.parse("{ \"$ln\" : 2}")); + void shouldRenderMethodReferenceLn() { + assertThat(transform("ln(2)")).isEqualTo(Document.parse("{ \"$ln\" : 2}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLog() { - assertThat(transform("log(100, 10)")).isEqualTo((Object) Document.parse("{ \"$log\" : [ 100 , 10]}")); + void shouldRenderMethodReferenceLog() { + assertThat(transform("log(100, 10)")).isEqualTo(Document.parse("{ \"$log\" : [ 100 , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLog10() { - assertThat(transform("log10(100)")).isEqualTo((Object) Document.parse("{ \"$log10\" : 100}")); + void shouldRenderMethodReferenceLog10() { + assertThat(transform("log10(100)")).isEqualTo(Document.parse("{ \"$log10\" : 100}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeMod() { - assertThat(transform("mod(a, b)")).isEqualTo((Object) Document.parse("{ \"$mod\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeMod() { + assertThat(transform("mod(a, b)")).isEqualTo(Document.parse("{ \"$mod\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeMultiply() { - assertThat(transform("multiply(a, b)")).isEqualTo((Object) Document.parse("{ \"$multiply\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeMultiply() { + assertThat(transform("multiply(a, b)")).isEqualTo(Document.parse("{ \"$multiply\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodePow() { - assertThat(transform("pow(a, 2)")).isEqualTo((Object) Document.parse("{ \"$pow\" : [ \"$a\" , 2]}")); + void shouldRenderMethodReferenceNodePow() { + assertThat(transform("pow(a, 2)")).isEqualTo(Document.parse("{ \"$pow\" : [ \"$a\" , 2]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceSqrt() { - assertThat(transform("sqrt(2)")).isEqualTo((Object) Document.parse("{ \"$sqrt\" : 2}")); + void shouldRenderMethodReferenceSqrt() { + assertThat(transform("sqrt(2)")).isEqualTo(Document.parse("{ \"$sqrt\" : 2}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSubtract() { - assertThat(transform("subtract(a, b)")).isEqualTo((Object) Document.parse("{ \"$subtract\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeSubtract() { + assertThat(transform("subtract(a, b)")).isEqualTo(Document.parse("{ \"$subtract\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceTrunc() { - assertThat(transform("trunc(2.1)")).isEqualTo((Object) Document.parse("{ \"$trunc\" : 2.1}")); + void shouldRenderMethodReferenceTrunc() { + assertThat(transform("trunc(2.1)")).isEqualTo(Document.parse("{ \"$trunc\" : 2.1}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeConcat() { + void shouldRenderMethodReferenceNodeConcat() { assertThat(transform("concat(a, b, 'c')")) - .isEqualTo((Object) Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}")); + .isEqualTo(Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSubstrc() { - assertThat(transform("substr(a, 0, 1)")).isEqualTo((Object) Document.parse("{ \"$substr\" : [ \"$a\" , 0 , 1]}")); + void shouldRenderMethodReferenceNodeSubstrc() { + assertThat(transform("substr(a, 0, 1)")).isEqualTo(Document.parse("{ \"$substr\" : [ \"$a\" , 0 , 1]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceToLower() { - assertThat(transform("toLower(a)")).isEqualTo((Object) Document.parse("{ \"$toLower\" : \"$a\"}")); + void shouldRenderMethodReferenceToLower() { + assertThat(transform("toLower(a)")).isEqualTo(Document.parse("{ \"$toLower\" : \"$a\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceToUpper() { - assertThat(transform("toUpper(a)")).isEqualTo((Object) Document.parse("{ \"$toUpper\" : \"$a\"}")); + void shouldRenderMethodReferenceToUpper() { + assertThat(transform("toUpper(a)")).isEqualTo(Document.parse("{ \"$toUpper\" : \"$a\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeStrCaseCmp() { + void shouldRenderMethodReferenceNodeStrCaseCmp() { assertThat(transform("strcasecmp(a, b)")) - .isEqualTo((Object) Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}")); + .isEqualTo(Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceMeta() { - assertThat(transform("meta('textScore')")).isEqualTo((Object) Document.parse("{ \"$meta\" : \"textScore\"}")); + void shouldRenderMethodReferenceMeta() { + assertThat(transform("meta('textScore')")).isEqualTo(Document.parse("{ \"$meta\" : \"textScore\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeArrayElemAt() { + void shouldRenderMethodReferenceNodeArrayElemAt() { assertThat(transform("arrayElemAt(a, 10)")) - .isEqualTo((Object) Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}")); + .isEqualTo(Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeConcatArrays() { + void shouldRenderMethodReferenceNodeConcatArrays() { assertThat(transform("concatArrays(a, b, c)")) - .isEqualTo((Object) Document.parse("{ \"$concatArrays\" : [ \"$a\" , \"$b\" , \"$c\"]}")); + .isEqualTo(Document.parse("{ \"$concatArrays\" : [ \"$a\" , \"$b\" , \"$c\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeFilter() { - assertThat(transform("filter(a, 'num', '$$num' > 10)")).isEqualTo((Object) Document.parse( + void shouldRenderMethodReferenceNodeFilter() { + assertThat(transform("filter(a, 'num', '$$num' > 10)")).isEqualTo(Document.parse( "{ \"$filter\" : { \"input\" : \"$a\" , \"as\" : \"num\" , \"cond\" : { \"$gt\" : [ \"$$num\" , 10]}}}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceIsArray() { - assertThat(transform("isArray(a)")).isEqualTo((Object) Document.parse("{ \"$isArray\" : \"$a\"}")); + void shouldRenderMethodReferenceIsArray() { + assertThat(transform("isArray(a)")).isEqualTo(Document.parse("{ \"$isArray\" : \"$a\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceIsSize() { - assertThat(transform("size(a)")).isEqualTo((Object) Document.parse("{ \"$size\" : \"$a\"}")); + void shouldRenderMethodReferenceIsSize() { + assertThat(transform("size(a)")).isEqualTo(Document.parse("{ \"$size\" : \"$a\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSlice() { - assertThat(transform("slice(a, 10)")).isEqualTo((Object) Document.parse("{ \"$slice\" : [ \"$a\" , 10]}")); + void shouldRenderMethodReferenceNodeSlice() { + assertThat(transform("slice(a, 10)")).isEqualTo(Document.parse("{ \"$slice\" : [ \"$a\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeMap() { - assertThat(transform("map(quizzes, 'grade', '$$grade' + 2)")).isEqualTo((Object) Document.parse( + void shouldRenderMethodReferenceNodeMap() { + assertThat(transform("map(quizzes, 'grade', '$$grade' + 2)")).isEqualTo(Document.parse( "{ \"$map\" : { \"input\" : \"$quizzes\" , \"as\" : \"grade\" , \"in\" : { \"$add\" : [ \"$$grade\" , 2]}}}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeLet() { - assertThat(transform("let({low:1, high:'$$low'}, gt('$$low', '$$high'))")).isEqualTo((Object) Document.parse( + void shouldRenderMethodReferenceNodeLet() { + assertThat(transform("let({low:1, high:'$$low'}, gt('$$low', '$$high'))")).isEqualTo(Document.parse( "{ \"$let\" : { \"vars\" : { \"low\" : 1 , \"high\" : \"$$low\"} , \"in\" : { \"$gt\" : [ \"$$low\" , \"$$high\"]}}}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLiteral() { - assertThat(transform("literal($1)")).isEqualTo((Object) Document.parse("{ \"$literal\" : \"$1\"}")); + void shouldRenderMethodReferenceLiteral() { + assertThat(transform("literal($1)")).isEqualTo(Document.parse("{ \"$literal\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceDayOfYear() { - assertThat(transform("dayOfYear($1)")).isEqualTo((Object) Document.parse("{ \"$dayOfYear\" : \"$1\"}")); + void shouldRenderMethodReferenceDayOfYear() { + assertThat(transform("dayOfYear($1)")).isEqualTo(Document.parse("{ \"$dayOfYear\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceDayOfMonth() { - assertThat(transform("dayOfMonth($1)")).isEqualTo((Object) Document.parse("{ \"$dayOfMonth\" : \"$1\"}")); + void shouldRenderMethodReferenceDayOfMonth() { + assertThat(transform("dayOfMonth($1)")).isEqualTo(Document.parse("{ \"$dayOfMonth\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceDayOfWeek() { - assertThat(transform("dayOfWeek($1)")).isEqualTo((Object) Document.parse("{ \"$dayOfWeek\" : \"$1\"}")); + void shouldRenderMethodReferenceDayOfWeek() { + assertThat(transform("dayOfWeek($1)")).isEqualTo(Document.parse("{ \"$dayOfWeek\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceYear() { - assertThat(transform("year($1)")).isEqualTo((Object) Document.parse("{ \"$year\" : \"$1\"}")); + void shouldRenderMethodReferenceYear() { + assertThat(transform("year($1)")).isEqualTo(Document.parse("{ \"$year\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceMonth() { - assertThat(transform("month($1)")).isEqualTo((Object) Document.parse("{ \"$month\" : \"$1\"}")); + void shouldRenderMethodReferenceMonth() { + assertThat(transform("month($1)")).isEqualTo(Document.parse("{ \"$month\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceWeek() { - assertThat(transform("week($1)")).isEqualTo((Object) Document.parse("{ \"$week\" : \"$1\"}")); + void shouldRenderMethodReferenceWeek() { + assertThat(transform("week($1)")).isEqualTo(Document.parse("{ \"$week\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceHour() { - assertThat(transform("hour($1)")).isEqualTo((Object) Document.parse("{ \"$hour\" : \"$1\"}")); + void shouldRenderMethodReferenceHour() { + assertThat(transform("hour($1)")).isEqualTo(Document.parse("{ \"$hour\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceMinute() { - assertThat(transform("minute($1)")).isEqualTo((Object) Document.parse("{ \"$minute\" : \"$1\"}")); + void shouldRenderMethodReferenceMinute() { + assertThat(transform("minute($1)")).isEqualTo(Document.parse("{ \"$minute\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceSecond() { - assertThat(transform("second($1)")).isEqualTo((Object) Document.parse("{ \"$second\" : \"$1\"}")); + void shouldRenderMethodReferenceSecond() { + assertThat(transform("second($1)")).isEqualTo(Document.parse("{ \"$second\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceMillisecond() { - assertThat(transform("millisecond($1)")).isEqualTo((Object) Document.parse("{ \"$millisecond\" : \"$1\"}")); + void shouldRenderMethodReferenceMillisecond() { + assertThat(transform("millisecond($1)")).isEqualTo(Document.parse("{ \"$millisecond\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceDateToString() { + void shouldRenderMethodReferenceDateToString() { assertThat(transform("dateToString('%Y-%m-%d', $date)")).isEqualTo( - (Object) Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}")); + Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceCond() { - assertThat(transform("cond(qty > 250, 30, 20)")).isEqualTo((Object) Document + void shouldRenderMethodReferenceCond() { + assertThat(transform("cond(qty > 250, 30, 20)")).isEqualTo( + Document .parse("{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeIfNull() { - assertThat(transform("ifNull(a, 10)")).isEqualTo((Object) Document.parse("{ \"$ifNull\" : [ \"$a\" , 10]}")); + void shouldRenderMethodReferenceNodeIfNull() { + assertThat(transform("ifNull(a, 10)")).isEqualTo(Document.parse("{ \"$ifNull\" : [ \"$a\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeSum() { - assertThat(transform("sum(a, b)")).isEqualTo((Object) Document.parse("{ \"$sum\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeSum() { + assertThat(transform("sum(a, b)")).isEqualTo(Document.parse("{ \"$sum\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeAvg() { - assertThat(transform("avg(a, b)")).isEqualTo((Object) Document.parse("{ \"$avg\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeAvg() { + assertThat(transform("avg(a, b)")).isEqualTo(Document.parse("{ \"$avg\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceFirst() { - assertThat(transform("first($1)")).isEqualTo((Object) Document.parse("{ \"$first\" : \"$1\"}")); + void shouldRenderMethodReferenceFirst() { + assertThat(transform("first($1)")).isEqualTo(Document.parse("{ \"$first\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceLast() { - assertThat(transform("last($1)")).isEqualTo((Object) Document.parse("{ \"$last\" : \"$1\"}")); + void shouldRenderMethodReferenceLast() { + assertThat(transform("last($1)")).isEqualTo(Document.parse("{ \"$last\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeMax() { - assertThat(transform("max(a, b)")).isEqualTo((Object) Document.parse("{ \"$max\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeMax() { + assertThat(transform("max(a, b)")).isEqualTo(Document.parse("{ \"$max\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeMin() { - assertThat(transform("min(a, b)")).isEqualTo((Object) Document.parse("{ \"$min\" : [ \"$a\" , \"$b\"]}")); + void shouldRenderMethodReferenceNodeMin() { + assertThat(transform("min(a, b)")).isEqualTo(Document.parse("{ \"$min\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodePush() { + void shouldRenderMethodReferenceNodePush() { assertThat(transform("push({'item':'$item', 'quantity':'$qty'})")) - .isEqualTo((Object) Document.parse("{ \"$push\" : { \"item\" : \"$item\" , \"quantity\" : \"$qty\"}}")); + .isEqualTo(Document.parse("{ \"$push\" : { \"item\" : \"$item\" , \"quantity\" : \"$qty\"}}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceAddToSet() { - assertThat(transform("addToSet($1)")).isEqualTo((Object) Document.parse("{ \"$addToSet\" : \"$1\"}")); + void shouldRenderMethodReferenceAddToSet() { + assertThat(transform("addToSet($1)")).isEqualTo(Document.parse("{ \"$addToSet\" : \"$1\"}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeStdDevPop() { + void shouldRenderMethodReferenceNodeStdDevPop() { assertThat(transform("stdDevPop(scores.score)")) - .isEqualTo((Object) Document.parse("{ \"$stdDevPop\" : [ \"$scores.score\"]}")); + .isEqualTo(Document.parse("{ \"$stdDevPop\" : [ \"$scores.score\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderMethodReferenceNodeStdDevSamp() { - assertThat(transform("stdDevSamp(age)")).isEqualTo((Object) Document.parse("{ \"$stdDevSamp\" : [ \"$age\"]}")); + void shouldRenderMethodReferenceNodeStdDevSamp() { + assertThat(transform("stdDevSamp(age)")).isEqualTo(Document.parse("{ \"$stdDevSamp\" : [ \"$age\"]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeEq() { - assertThat(transform("foo == 10")).isEqualTo((Object) Document.parse("{ \"$eq\" : [ \"$foo\" , 10]}")); + void shouldRenderOperationNodeEq() { + assertThat(transform("foo == 10")).isEqualTo(Document.parse("{ \"$eq\" : [ \"$foo\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeNe() { - assertThat(transform("foo != 10")).isEqualTo((Object) Document.parse("{ \"$ne\" : [ \"$foo\" , 10]}")); + void shouldRenderOperationNodeNe() { + assertThat(transform("foo != 10")).isEqualTo(Document.parse("{ \"$ne\" : [ \"$foo\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeGt() { - assertThat(transform("foo > 10")).isEqualTo((Object) Document.parse("{ \"$gt\" : [ \"$foo\" , 10]}")); + void shouldRenderOperationNodeGt() { + assertThat(transform("foo > 10")).isEqualTo(Document.parse("{ \"$gt\" : [ \"$foo\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeGte() { - assertThat(transform("foo >= 10")).isEqualTo((Object) Document.parse("{ \"$gte\" : [ \"$foo\" , 10]}")); + void shouldRenderOperationNodeGte() { + assertThat(transform("foo >= 10")).isEqualTo(Document.parse("{ \"$gte\" : [ \"$foo\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeLt() { - assertThat(transform("foo < 10")).isEqualTo((Object) Document.parse("{ \"$lt\" : [ \"$foo\" , 10]}")); + void shouldRenderOperationNodeLt() { + assertThat(transform("foo < 10")).isEqualTo(Document.parse("{ \"$lt\" : [ \"$foo\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeLte() { - assertThat(transform("foo <= 10")).isEqualTo((Object) Document.parse("{ \"$lte\" : [ \"$foo\" , 10]}")); + void shouldRenderOperationNodeLte() { + assertThat(transform("foo <= 10")).isEqualTo(Document.parse("{ \"$lte\" : [ \"$foo\" , 10]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodePow() { - assertThat(transform("foo^2")).isEqualTo((Object) Document.parse("{ \"$pow\" : [ \"$foo\" , 2]}")); + void shouldRenderOperationNodePow() { + assertThat(transform("foo^2")).isEqualTo(Document.parse("{ \"$pow\" : [ \"$foo\" , 2]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeOr() { - assertThat(transform("true || false")).isEqualTo((Object) Document.parse("{ \"$or\" : [ true , false]}")); + void shouldRenderOperationNodeOr() { + assertThat(transform("true || false")).isEqualTo(Document.parse("{ \"$or\" : [ true , false]}")); } @Test // DATAMONGO-1530 - public void shouldRenderComplexOperationNodeOr() { + void shouldRenderComplexOperationNodeOr() { assertThat(transform("1+2 || concat(a, b) || true")).isEqualTo( - (Object) Document.parse("{ \"$or\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); + Document.parse("{ \"$or\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); } @Test // DATAMONGO-1530 - public void shouldRenderOperationNodeAnd() { - assertThat(transform("true && false")).isEqualTo((Object) Document.parse("{ \"$and\" : [ true , false]}")); + void shouldRenderOperationNodeAnd() { + assertThat(transform("true && false")).isEqualTo(Document.parse("{ \"$and\" : [ true , false]}")); } @Test // DATAMONGO-1530 - public void shouldRenderComplexOperationNodeAnd() { - assertThat(transform("1+2 && concat(a, b) && true")).isEqualTo((Object) Document + void shouldRenderComplexOperationNodeAnd() { + assertThat(transform("1+2 && concat(a, b) && true")).isEqualTo( + Document .parse("{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); } @Test // DATAMONGO-1530 - public void shouldRenderNotCorrectly() { - assertThat(transform("!true")).isEqualTo((Object) Document.parse("{ \"$not\" : [ true]}")); + void shouldRenderNotCorrectly() { + assertThat(transform("!true")).isEqualTo(Document.parse("{ \"$not\" : [ true]}")); } @Test // DATAMONGO-1530 - public void shouldRenderComplexNotCorrectly() { + void shouldRenderComplexNotCorrectly() { assertThat(transform("!(foo > 10)")) - .isEqualTo((Object) Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}")); + .isEqualTo(Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceIndexOfBytes() { + void shouldRenderMethodReferenceIndexOfBytes() { assertThat(transform("indexOfBytes(item, 'foo')")) .isEqualTo(Document.parse("{ \"$indexOfBytes\" : [ \"$item\" , \"foo\"]}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceIndexOfCP() { + void shouldRenderMethodReferenceIndexOfCP() { assertThat(transform("indexOfCP(item, 'foo')")) .isEqualTo(Document.parse("{ \"$indexOfCP\" : [ \"$item\" , \"foo\"]}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceSplit() { + void shouldRenderMethodReferenceSplit() { assertThat(transform("split(item, ',')")).isEqualTo(Document.parse("{ \"$split\" : [ \"$item\" , \",\"]}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceStrLenBytes() { + void shouldRenderMethodReferenceStrLenBytes() { assertThat(transform("strLenBytes(item)")).isEqualTo(Document.parse("{ \"$strLenBytes\" : \"$item\"}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceStrLenCP() { + void shouldRenderMethodReferenceStrLenCP() { assertThat(transform("strLenCP(item)")).isEqualTo(Document.parse("{ \"$strLenCP\" : \"$item\"}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodSubstrCP() { + void shouldRenderMethodSubstrCP() { assertThat(transform("substrCP(item, 0, 5)")).isEqualTo(Document.parse("{ \"$substrCP\" : [ \"$item\" , 0 , 5]}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceReverseArray() { + void shouldRenderMethodReferenceReverseArray() { assertThat(transform("reverseArray(array)")).isEqualTo(Document.parse("{ \"$reverseArray\" : \"$array\"}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceReduce() { + void shouldRenderMethodReferenceReduce() { assertThat(transform("reduce(field, '', {'$concat':{'$$value','$$this'}})")).isEqualTo(Document.parse( "{ \"$reduce\" : { \"input\" : \"$field\" , \"initialValue\" : \"\" , \"in\" : { \"$concat\" : [ \"$$value\" , \"$$this\"]}}}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceZip() { + void shouldRenderMethodReferenceZip() { assertThat(transform("zip(new String[]{'$array1', '$array2'})")) .isEqualTo(Document.parse("{ \"$zip\" : { \"inputs\" : [ \"$array1\" , \"$array2\"]}}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodReferenceZipWithOptionalArgs() { + void shouldRenderMethodReferenceZipWithOptionalArgs() { assertThat(transform("zip(new String[]{'$array1', '$array2'}, true, new int[]{1,2})")).isEqualTo(Document.parse( "{ \"$zip\" : { \"inputs\" : [ \"$array1\" , \"$array2\"] , \"useLongestLength\" : true , \"defaults\" : [ 1 , 2]}}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodIn() { + void shouldRenderMethodIn() { assertThat(transform("in('item', array)")).isEqualTo(Document.parse("{ \"$in\" : [ \"item\" , \"$array\"]}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodRefereneIsoDayOfWeek() { + void shouldRenderMethodRefereneIsoDayOfWeek() { assertThat(transform("isoDayOfWeek(date)")).isEqualTo(Document.parse("{ \"$isoDayOfWeek\" : \"$date\"}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodRefereneIsoWeek() { + void shouldRenderMethodRefereneIsoWeek() { assertThat(transform("isoWeek(date)")).isEqualTo(Document.parse("{ \"$isoWeek\" : \"$date\"}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodRefereneIsoWeekYear() { + void shouldRenderMethodRefereneIsoWeekYear() { assertThat(transform("isoWeekYear(date)")).isEqualTo(Document.parse("{ \"$isoWeekYear\" : \"$date\"}")); } @Test // DATAMONGO-1548 - public void shouldRenderMethodRefereneType() { + void shouldRenderMethodRefereneType() { assertThat(transform("type(a)")).isEqualTo(Document.parse("{ \"$type\" : \"$a\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderArrayToObjectWithFieldReference() { + void shouldRenderArrayToObjectWithFieldReference() { assertThat(transform("arrayToObject(field)")).isEqualTo(Document.parse("{ \"$arrayToObject\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderArrayToObjectWithArray() { + void shouldRenderArrayToObjectWithArray() { assertThat(transform("arrayToObject(new String[]{'key', 'value'})")) .isEqualTo(Document.parse("{ \"$arrayToObject\" : [\"key\", \"value\"]}")); } @Test // DATAMONGO-2077 - public void shouldRenderObjectToArrayWithFieldReference() { + void shouldRenderObjectToArrayWithFieldReference() { assertThat(transform("objectToArray(field)")).isEqualTo(Document.parse("{ \"$objectToArray\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderMergeObjects() { + void shouldRenderMergeObjects() { assertThat(transform("mergeObjects(field1, $$ROOT)")) .isEqualTo(Document.parse("{ \"$mergeObjects\" : [\"$field1\", \"$$ROOT\"]}")); } @Test // DATAMONGO-2077 - public void shouldRenderTrimWithoutChars() { + void shouldRenderTrimWithoutChars() { assertThat(transform("trim(field)")).isEqualTo(Document.parse("{ \"$trim\" : {\"input\" : \"$field\"}}")); } @Test // DATAMONGO-2077 - public void shouldRenderTrimWithChars() { + void shouldRenderTrimWithChars() { assertThat(transform("trim(field, 'ie')")) .isEqualTo(Document.parse("{ \"$trim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderTrimWithCharsFromFieldReference() { + void shouldRenderTrimWithCharsFromFieldReference() { assertThat(transform("trim(field1, field2)")) .isEqualTo(Document.parse("{ \"$trim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderLtrimWithoutChars() { + void shouldRenderLtrimWithoutChars() { assertThat(transform("ltrim(field)")).isEqualTo(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field\"}}")); } @Test // DATAMONGO-2077 - public void shouldRenderLtrimWithChars() { + void shouldRenderLtrimWithChars() { assertThat(transform("ltrim(field, 'ie')")) .isEqualTo(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderLtrimWithCharsFromFieldReference() { + void shouldRenderLtrimWithCharsFromFieldReference() { assertThat(transform("ltrim(field1, field2)")) .isEqualTo(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderRtrimWithoutChars() { + void shouldRenderRtrimWithoutChars() { assertThat(transform("rtrim(field)")).isEqualTo(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field\"}}")); } @Test // DATAMONGO-2077 - public void shouldRenderRtrimWithChars() { + void shouldRenderRtrimWithChars() { assertThat(transform("rtrim(field, 'ie')")) .isEqualTo(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderRtrimWithCharsFromFieldReference() { + void shouldRenderRtrimWithCharsFromFieldReference() { assertThat(transform("rtrim(field1, field2)")) .isEqualTo(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderConvertWithoutOptionalParameters() { + void shouldRenderConvertWithoutOptionalParameters() { assertThat(transform("convert(field, 'string')")) .isEqualTo(Document.parse("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"string\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderConvertWithOnError() { + void shouldRenderConvertWithOnError() { assertThat(transform("convert(field, 'int', 'Not an integer.')")).isEqualTo(Document .parse("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderConvertWithOnErrorOnNull() { + void shouldRenderConvertWithOnErrorOnNull() { assertThat(transform("convert(field, 'int', 'Not an integer.', -1)")).isEqualTo(Document.parse( "{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\", \"onNull\" : -1 }}")); } @Test // DATAMONGO-2077 - public void shouldRenderToBool() { + void shouldRenderToBool() { assertThat(transform("toBool(field)")).isEqualTo(Document.parse("{ \"$toBool\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToDate() { + void shouldRenderToDate() { assertThat(transform("toDate(field)")).isEqualTo(Document.parse("{ \"$toDate\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToDecimal() { + void shouldRenderToDecimal() { assertThat(transform("toDecimal(field)")).isEqualTo(Document.parse("{ \"$toDecimal\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToDouble() { + void shouldRenderToDouble() { assertThat(transform("toDouble(field)")).isEqualTo(Document.parse("{ \"$toDouble\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToInt() { + void shouldRenderToInt() { assertThat(transform("toInt(field)")).isEqualTo(Document.parse("{ \"$toInt\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToLong() { + void shouldRenderToLong() { assertThat(transform("toLong(field)")).isEqualTo(Document.parse("{ \"$toLong\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToObjectId() { + void shouldRenderToObjectId() { assertThat(transform("toObjectId(field)")).isEqualTo(Document.parse("{ \"$toObjectId\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderToString() { + void shouldRenderToString() { assertThat(transform("toString(field)")).isEqualTo(Document.parse("{ \"$toString\" : \"$field\"}")); } @Test // DATAMONGO-2077 - public void shouldRenderDateFromStringWithoutOptionalParameters() { + void shouldRenderDateFromStringWithoutOptionalParameters() { assertThat(transform("dateFromString(field)")) .isEqualTo(Document.parse("{ \"$dateFromString\" : {\"dateString\" : \"$field\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderDateFromStringWithFormat() { + void shouldRenderDateFromStringWithFormat() { assertThat(transform("dateFromString(field, 'DD-MM-YYYY')")).isEqualTo( Document.parse("{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderDateFromStringWithFormatAndTimezone() { + void shouldRenderDateFromStringWithFormatAndTimezone() { assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC')")).isEqualTo(Document.parse( "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\" }}")); } @Test // DATAMONGO-2077 - public void shouldRenderDateFromStringWithFormatTimezoneAndOnError() { + void shouldRenderDateFromStringWithFormatTimezoneAndOnError() { assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1)")).isEqualTo(Document.parse( "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1 }}")); } @Test // DATAMONGO-2077 - public void shouldRenderDateFromStringWithFormatTimezoneOnErrorAndOnNull() { + void shouldRenderDateFromStringWithFormatTimezoneOnErrorAndOnNull() { assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1, -2)")).isEqualTo(Document.parse( "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1, \"onNull\" : -2}}")); } @Test // DATAMONGO-2077, DATAMONGO-2671 - public void shouldRenderDateFromParts() { + void shouldRenderDateFromParts() { assertThat(transform("dateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo(Document.parse( "{ \"$dateFromParts\" : {\"year\" : \"$y\", \"month\" : \"$m\", \"day\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}")); } @Test // DATAMONGO-2077, DATAMONGO-2671 - public void shouldRenderIsoDateFromParts() { + void shouldRenderIsoDateFromParts() { assertThat(transform("isoDateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo(Document.parse( "{ \"$dateFromParts\" : {\"isoWeekYear\" : \"$y\", \"isoWeek\" : \"$m\", \"isoDayOfWeek\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}")); } @Test // DATAMONGO-2077 - public void shouldRenderDateToParts() { + void shouldRenderDateToParts() { assertThat(transform("dateToParts(field, 'UTC', false)")).isEqualTo( Document.parse("{ \"$dateToParts\" : {\"date\" : \"$field\", \"timezone\" : \"UTC\", \"iso8601\" : false}}")); } @Test // DATAMONGO-2077 - public void shouldRenderIndexOfArray() { + void shouldRenderIndexOfArray() { assertThat(transform("indexOfArray(field, 2)")) .isEqualTo(Document.parse("{ \"$indexOfArray\" : [\"$field\", 2 ]}")); } @Test // DATAMONGO-2077 - public void shouldRenderRange() { + void shouldRenderRange() { assertThat(transform("range(0, 10, 2)")).isEqualTo(Document.parse("{ \"$range\" : [0, 10, 2 ]}")); } @Test // DATAMONGO-2370 - public void shouldRenderRound() { + void shouldRenderRound() { assertThat(transform("round(field)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\"]}")); } @Test // DATAMONGO-2370 - public void shouldRenderRoundWithPlace() { + void shouldRenderRoundWithPlace() { assertThat(transform("round(field, 2)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\", 2]}")); } @@ -985,6 +988,7 @@ void rendersShiftWithDefault() { .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }")); } + @Nullable private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index dfa87dd3c7..daaad49963 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2506,13 +2506,16 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (*via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` +| `abs`, `add` (via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` + +| Document Operators +| `rank`, `denseRank`, `documentNumber`, `shift` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` | Comparison Aggregation Operators -| `eq` (*via: `is`), `gt`, `gte`, `lt`, `lte`, `ne` +| `eq` (via: `is`), `gt`, `gte`, `lt`, `lte`, `ne` | Array Aggregation Operators | `arrayElementAt`, `arrayToObject`, `concatArrays`, `filter`, `in`, `indexOfArray`, `isArray`, `range`, `reverseArray`, `reduce`, `size`, `slice`, `zip` From 0c481feb722d3d301445d8135633363b24c1abeb Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 11:06:41 +0200 Subject: [PATCH 0493/1381] Extract Aggregation Framework and GridFS docs in own source files. Closes #3786 --- .../reference/aggregation-framework.adoc | 656 +++++++++++++++ src/main/asciidoc/reference/gridfs.adoc | 115 +++ src/main/asciidoc/reference/mongodb.adoc | 776 +----------------- 3 files changed, 774 insertions(+), 773 deletions(-) create mode 100644 src/main/asciidoc/reference/aggregation-framework.adoc create mode 100644 src/main/asciidoc/reference/gridfs.adoc diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc new file mode 100644 index 0000000000..a843af17f4 --- /dev/null +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -0,0 +1,656 @@ +[[mongo.aggregation]] +== Aggregation Framework Support + +Spring Data MongoDB provides support for the Aggregation Framework introduced to MongoDB in version 2.2. + +For further information, see the full https://docs.mongodb.org/manual/aggregation/[reference documentation] of the aggregation framework and other data aggregation tools for MongoDB. + +[[mongo.aggregation.basic-concepts]] +=== Basic Concepts + +The Aggregation Framework support in Spring Data MongoDB is based on the following key abstractions: `Aggregation`, `AggregationDefinition`, and `AggregationResults`. + +* `Aggregation` ++ +An `Aggregation` represents a MongoDB `aggregate` operation and holds the description of the aggregation pipeline instructions. Aggregations are created by invoking the appropriate `newAggregation(…)` static factory method of the `Aggregation` class, which takes a list of `AggregateOperation` and an optional input class. ++ +The actual aggregate operation is run by the `aggregate` method of the `MongoTemplate`, which takes the desired output class as a parameter. ++ +* `TypedAggregation` ++ +A `TypedAggregation`, just like an `Aggregation`, holds the instructions of the aggregation pipeline and a reference to the input type, that is used for mapping domain properties to actual document fields. ++ +At runtime, field references get checked against the given input type, considering potential `@Field` annotations. +[NOTE] +==== +Changed in 3.2 referencing non-existent properties does no longer raise errors. To restore the previous behaviour use the `strictMapping` option of `AggregationOptions`. +==== +* `AggregationDefinition` ++ +An `AggregationDefinition` represents a MongoDB aggregation pipeline operation and describes the processing that should be performed in this aggregation step. Although you could manually create an `AggregationDefinition`, we recommend using the static factory methods provided by the `Aggregate` class to construct an `AggregateOperation`. ++ +* `AggregationResults` ++ +`AggregationResults` is the container for the result of an aggregate operation. It provides access to the raw aggregation result, in the form of a `Document` to the mapped objects and other information about the aggregation. ++ +The following listing shows the canonical example for using the Spring Data MongoDB support for the MongoDB Aggregation Framework: ++ +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +Aggregation agg = newAggregation( + pipelineOP1(), + pipelineOP2(), + pipelineOPn() +); + +AggregationResults results = mongoTemplate.aggregate(agg, "INPUT_COLLECTION_NAME", OutputType.class); +List mappedResult = results.getMappedResults(); +---- + +Note that, if you provide an input class as the first parameter to the `newAggregation` method, the `MongoTemplate` derives the name of the input collection from this class. Otherwise, if you do not not specify an input class, you must provide the name of the input collection explicitly. If both an input class and an input collection are provided, the latter takes precedence. + +[[mongo.aggregation.supported-aggregation-operations]] +=== Supported Aggregation Operations + +The MongoDB Aggregation Framework provides the following types of aggregation operations: + +* Pipeline Aggregation Operators +* Group Aggregation Operators +* Boolean Aggregation Operators +* Comparison Aggregation Operators +* Arithmetic Aggregation Operators +* String Aggregation Operators +* Date Aggregation Operators +* Array Aggregation Operators +* Conditional Aggregation Operators +* Lookup Aggregation Operators +* Convert Aggregation Operators +* Object Aggregation Operators +* Script Aggregation Operators + +At the time of this writing, we provide support for the following Aggregation Operations in Spring Data MongoDB: + +.Aggregation Operations currently supported by Spring Data MongoDB +[cols="2*"] +|=== +| Pipeline Aggregation Operators +| `bucket`, `bucketAuto`, `count`, `facet`, `geoNear`, `graphLookup`, `group`, `limit`, `lookup`, `match`, `project`, `replaceRoot`, `skip`, `sort`, `unwind` + +| Set Aggregation Operators +| `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue` + +| Group/Accumulator Aggregation Operators +| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` + +| Arithmetic Aggregation Operators +| `abs`, `add` (via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` + +| Document Operators +| `rank`, `denseRank`, `documentNumber`, `shift` + +| String Aggregation Operators +| `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` + +| Comparison Aggregation Operators +| `eq` (via: `is`), `gt`, `gte`, `lt`, `lte`, `ne` + +| Array Aggregation Operators +| `arrayElementAt`, `arrayToObject`, `concatArrays`, `filter`, `in`, `indexOfArray`, `isArray`, `range`, `reverseArray`, `reduce`, `size`, `slice`, `zip` + +| Literal Operators +| `literal` + +| Date Aggregation Operators +| `dayOfYear`, `dayOfMonth`, `dayOfWeek`, `year`, `month`, `week`, `hour`, `minute`, `second`, `millisecond`, `dateToString`, `dateFromString`, `dateFromParts`, `dateToParts`, `isoDayOfWeek`, `isoWeek`, `isoWeekYear` + +| Variable Operators +| `map` + +| Conditional Aggregation Operators +| `cond`, `ifNull`, `switch` + +| Type Aggregation Operators +| `type` + +| Convert Aggregation Operators +| `convert`, `toBool`, `toDate`, `toDecimal`, `toDouble`, `toInt`, `toLong`, `toObjectId`, `toString` + +| Object Aggregation Operators +| `objectToArray`, `mergeObjects` + +| Script Aggregation Operators +| `function`, `accumulator` +|=== + +* The operation is mapped or added by Spring Data MongoDB. + +Note that the aggregation operations not listed here are currently not supported by Spring Data MongoDB.Comparison aggregation operators are expressed as `Criteria` expressions. + +[[mongo.aggregation.projection]] +=== Projection Expressions + +Projection expressions are used to define the fields that are the outcome of a particular aggregation step. Projection expressions can be defined through the `project` method of the `Aggregation` class, either by passing a list of `String` objects or an aggregation framework `Fields` object. The projection can be extended with additional fields through a fluent API by using the `and(String)` method and aliased by using the `as(String)` method. +Note that you can also define fields with aliases by using the `Fields.field` static factory method of the aggregation framework, which you can then use to construct a new `Fields` instance. References to projected fields in later aggregation stages are valid only for the field names of included fields or their aliases (including newly defined fields and their aliases). Fields not included in the projection cannot be referenced in later aggregation stages. The following listings show examples of projection expression: + +.Projection expression examples +==== +[source,java] +---- +// generates {$project: {name: 1, netPrice: 1}} +project("name", "netPrice") + +// generates {$project: {thing1: $thing2}} +project().and("thing1").as("thing2") + +// generates {$project: {a: 1, b: 1, thing2: $thing1}} +project("a","b").and("thing1").as("thing2") +---- +==== + +.Multi-Stage Aggregation using Projection and Sorting +==== +[source,java] +---- +// generates {$project: {name: 1, netPrice: 1}}, {$sort: {name: 1}} +project("name", "netPrice"), sort(ASC, "name") + +// generates {$project: {name: $firstname}}, {$sort: {name: 1}} +project().and("firstname").as("name"), sort(ASC, "name") + +// does not work +project().and("firstname").as("name"), sort(ASC, "firstname") +---- +==== + +More examples for project operations can be found in the `AggregationTests` class. Note that further details regarding the projection expressions can be found in the https://docs.mongodb.org/manual/reference/operator/aggregation/project/#pipe._S_project[corresponding section] of the MongoDB Aggregation Framework reference documentation. + +[[mongo.aggregation.facet]] +=== Faceted Classification + +As of Version 3.4, MongoDB supports faceted classification by using the Aggregation Framework. A faceted classification uses semantic categories (either general or subject-specific) that are combined to create the full classification entry. Documents flowing through the aggregation pipeline are classified into buckets. A multi-faceted classification enables various aggregations on the same set of input documents, without needing to retrieve the input documents multiple times. + +==== Buckets + +Bucket operations categorize incoming documents into groups, called buckets, based on a specified expression and bucket boundaries. Bucket operations require a grouping field or a grouping expression. You can define them by using the `bucket()` and `bucketAuto()` methods of the `Aggregate` class. `BucketOperation` and `BucketAutoOperation` can expose accumulations based on aggregation expressions for input documents. You can extend the bucket operation with additional parameters through a fluent API by using the `with…()` methods and the `andOutput(String)` method. You can alias the operation by using the `as(String)` method. Each bucket is represented as a document in the output. + +`BucketOperation` takes a defined set of boundaries to group incoming documents into these categories. Boundaries are required to be sorted. The following listing shows some examples of bucket operations: + +.Bucket operation examples +==== +[source,java] +---- +// generates {$bucket: {groupBy: $price, boundaries: [0, 100, 400]}} +bucket("price").withBoundaries(0, 100, 400); + +// generates {$bucket: {groupBy: $price, default: "Other" boundaries: [0, 100]}} +bucket("price").withBoundaries(0, 100).withDefault("Other"); + +// generates {$bucket: {groupBy: $price, boundaries: [0, 100], output: { count: { $sum: 1}}}} +bucket("price").withBoundaries(0, 100).andOutputCount().as("count"); + +// generates {$bucket: {groupBy: $price, boundaries: [0, 100], 5, output: { titles: { $push: "$title"}}} +bucket("price").withBoundaries(0, 100).andOutput("title").push().as("titles"); +---- +==== + +`BucketAutoOperation` determines boundaries in an attempt to evenly distribute documents into a specified number of buckets. `BucketAutoOperation` optionally takes a granularity value that specifies the https://en.wikipedia.org/wiki/Preferred_number[preferred number] series to use to ensure that the calculated boundary edges end on preferred round numbers or on powers of 10. The following listing shows examples of bucket operations: + +.Bucket operation examples +==== +[source,java] +---- +// generates {$bucketAuto: {groupBy: $price, buckets: 5}} +bucketAuto("price", 5) + +// generates {$bucketAuto: {groupBy: $price, buckets: 5, granularity: "E24"}} +bucketAuto("price", 5).withGranularity(Granularities.E24).withDefault("Other"); + +// generates {$bucketAuto: {groupBy: $price, buckets: 5, output: { titles: { $push: "$title"}}} +bucketAuto("price", 5).andOutput("title").push().as("titles"); +---- +==== + +To create output fields in buckets, bucket operations can use `AggregationExpression` through `andOutput()` and <> through `andOutputExpression()`. + +Note that further details regarding bucket expressions can be found in the https://docs.mongodb.org/manual/reference/operator/aggregation/bucket/[`$bucket` section] and +https://docs.mongodb.org/manual/reference/operator/aggregation/bucketAuto/[`$bucketAuto` section] of the MongoDB Aggregation Framework reference documentation. + +==== Multi-faceted Aggregation + +Multiple aggregation pipelines can be used to create multi-faceted aggregations that characterize data across multiple dimensions (or facets) within a single aggregation stage. Multi-faceted aggregations provide multiple filters and categorizations to guide data browsing and analysis. A common implementation of faceting is how many online retailers provide ways to narrow down search results by applying filters on product price, manufacturer, size, and other factors. + +You can define a `FacetOperation` by using the `facet()` method of the `Aggregation` class. You can customize it with multiple aggregation pipelines by using the `and()` method. Each sub-pipeline has its own field in the output document where its results are stored as an array of documents. + +Sub-pipelines can project and filter input documents prior to grouping. Common use cases include extraction of date parts or calculations before categorization. The following listing shows facet operation examples: + +.Facet operation examples +==== +[source,java] +---- +// generates {$facet: {categorizedByPrice: [ { $match: { price: {$exists : true}}}, { $bucketAuto: {groupBy: $price, buckets: 5}}]}} +facet(match(Criteria.where("price").exists(true)), bucketAuto("price", 5)).as("categorizedByPrice")) + +// generates {$facet: {categorizedByCountry: [ { $match: { country: {$exists : true}}}, { $sortByCount: "$country"}]}} +facet(match(Criteria.where("country").exists(true)), sortByCount("country")).as("categorizedByCountry")) + +// generates {$facet: {categorizedByYear: [ +// { $project: { title: 1, publicationYear: { $year: "publicationDate"}}}, +// { $bucketAuto: {groupBy: $price, buckets: 5, output: { titles: {$push:"$title"}}} +// ]}} +facet(project("title").and("publicationDate").extractYear().as("publicationYear"), + bucketAuto("publicationYear", 5).andOutput("title").push().as("titles")) + .as("categorizedByYear")) +---- +==== + +Note that further details regarding facet operation can be found in the https://docs.mongodb.org/manual/reference/operator/aggregation/facet/[`$facet` section] of the MongoDB Aggregation Framework reference documentation. + +[[mongo.aggregation.sort-by-count]] +==== Sort By Count + +Sort by count operations group incoming documents based on the value of a specified expression, compute the count of documents in each distinct group, and sort the results by count. It offers a handy shortcut to apply sorting when using <>. Sort by count operations require a grouping field or grouping expression. The following listing shows a sort by count example: + +.Sort by count example +==== +[source,java] +---- +// generates { $sortByCount: "$country" } +sortByCount("country"); +---- +==== + +A sort by count operation is equivalent to the following BSON (Binary JSON): + +---- +{ $group: { _id: , count: { $sum: 1 } } }, +{ $sort: { count: -1 } } +---- + +[[mongo.aggregation.projection.expressions]] +==== Spring Expression Support in Projection Expressions + +We support the use of SpEL expressions in projection expressions through the `andExpression` method of the `ProjectionOperation` and `BucketOperation` classes. This feature lets you define the desired expression as a SpEL expression. On running a query, the SpEL expression is translated into a corresponding MongoDB projection expression part. This arrangement makes it much easier to express complex calculations. + +===== Complex Calculations with SpEL expressions + +Consider the following SpEL expression: + +[source,java] +---- +1 + (q + 1) / (q - 1) +---- + +The preceding expression is translated into the following projection expression part: + +[source,javascript] +---- +{ "$add" : [ 1, { + "$divide" : [ { + "$add":["$q", 1]}, { + "$subtract":[ "$q", 1]} + ] +}]} +---- + +You can see examples in more context in <> and <>. You can find more usage examples for supported SpEL expression constructs in `SpelExpressionTransformerUnitTests`. The following table shows the SpEL transformations supported by Spring Data MongoDB: + +.Supported SpEL transformations +[%header,cols="2"] +|=== +| SpEL Expression +| Mongo Expression Part +| a == b +| { $eq : [$a, $b] } +| a != b +| { $ne : [$a , $b] } +| a > b +| { $gt : [$a, $b] } +| a >= b +| { $gte : [$a, $b] } +| a < b +| { $lt : [$a, $b] } +| a <= b +| { $lte : [$a, $b] } +| a + b +| { $add : [$a, $b] } +| a - b +| { $subtract : [$a, $b] } +| a * b +| { $multiply : [$a, $b] } +| a / b +| { $divide : [$a, $b] } +| a^b +| { $pow : [$a, $b] } +| a % b +| { $mod : [$a, $b] } +| a && b +| { $and : [$a, $b] } +| a \|\| b +| { $or : [$a, $b] } +| !a +| { $not : [$a] } +|=== + +In addition to the transformations shown in the preceding table, you can use standard SpEL operations such as `new` to (for example) create arrays and reference expressions through their names (followed by the arguments to use in brackets). The following example shows how to create an array in this fashion: + +[source,java] +---- +// { $setEquals : [$a, [5, 8, 13] ] } +.andExpression("setEquals(a, new int[]{5, 8, 13})"); +---- + +[[mongo.aggregation.examples]] +==== Aggregation Framework Examples + +The examples in this section demonstrate the usage patterns for the MongoDB Aggregation Framework with Spring Data MongoDB. + +[[mongo.aggregation.examples.example1]] +===== Aggregation Framework Example 1 + +In this introductory example, we want to aggregate a list of tags to get the occurrence count of a particular tag from a MongoDB collection (called `tags`) sorted by the occurrence count in descending order. This example demonstrates the usage of grouping, sorting, projections (selection), and unwinding (result splitting). + +[source,java] +---- +class TagCount { + String tag; + int n; +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +Aggregation agg = newAggregation( + project("tags"), + unwind("tags"), + group("tags").count().as("n"), + project("n").and("tag").previousOperation(), + sort(DESC, "n") +); + +AggregationResults results = mongoTemplate.aggregate(agg, "tags", TagCount.class); +List tagCount = results.getMappedResults(); +---- + +The preceding listing uses the following algorithm: + +. Create a new aggregation by using the `newAggregation` static factory method, to which we pass a list of aggregation operations. These aggregate operations define the aggregation pipeline of our `Aggregation`. +. Use the `project` operation to select the `tags` field (which is an array of strings) from the input collection. +. Use the `unwind` operation to generate a new document for each tag within the `tags` array. +. Use the `group` operation to define a group for each `tags` value for which we aggregate the occurrence count (by using the `count` aggregation operator and collecting the result in a new field called `n`). +. Select the `n` field and create an alias for the ID field generated from the previous group operation (hence the call to `previousOperation()`) with a name of `tag`. +. Use the `sort` operation to sort the resulting list of tags by their occurrence count in descending order. +. Call the `aggregate` method on `MongoTemplate` to let MongoDB perform the actual aggregation operation, with the created `Aggregation` as an argument. + +Note that the input collection is explicitly specified as the `tags` parameter to the `aggregate` Method. If the name of the input collection is not specified explicitly, it is derived from the input class passed as the first parameter to the `newAggreation` method. + +[[mongo.aggregation.examples.example2]] +===== Aggregation Framework Example 2 + +This example is based on the https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state[Largest and Smallest Cities by State] example from the MongoDB Aggregation Framework documentation. We added additional sorting to produce stable results with different MongoDB versions. Here we want to return the smallest and largest cities by population for each state by using the aggregation framework. This example demonstrates grouping, sorting, and projections (selection). + +[source,java] +---- +class ZipInfo { + String id; + String city; + String state; + @Field("pop") int population; + @Field("loc") double[] location; +} + +class City { + String name; + int population; +} + +class ZipInfoStats { + String id; + String state; + City biggestCity; + City smallestCity; +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +TypedAggregation aggregation = newAggregation(ZipInfo.class, + group("state", "city") + .sum("population").as("pop"), + sort(ASC, "pop", "state", "city"), + group("state") + .last("city").as("biggestCity") + .last("pop").as("biggestPop") + .first("city").as("smallestCity") + .first("pop").as("smallestPop"), + project() + .and("state").previousOperation() + .and("biggestCity") + .nested(bind("name", "biggestCity").and("population", "biggestPop")) + .and("smallestCity") + .nested(bind("name", "smallestCity").and("population", "smallestPop")), + sort(ASC, "state") +); + +AggregationResults result = mongoTemplate.aggregate(aggregation, ZipInfoStats.class); +ZipInfoStats firstZipInfoStats = result.getMappedResults().get(0); +---- + +Note that the `ZipInfo` class maps the structure of the given input-collection. The `ZipInfoStats` class defines the structure in the desired output format. + +The preceding listings use the following algorithm: + +. Use the `group` operation to define a group from the input-collection. The grouping criteria is the combination of the `state` and `city` fields, which forms the ID structure of the group. We aggregate the value of the `population` property from the grouped elements by using the `sum` operator and save the result in the `pop` field. +. Use the `sort` operation to sort the intermediate-result by the `pop`, `state` and `city` fields, in ascending order, such that the smallest city is at the top and the biggest city is at the bottom of the result. Note that the sorting on `state` and `city` is implicitly performed against the group ID fields (which Spring Data MongoDB handled). +. Use a `group` operation again to group the intermediate result by `state`. Note that `state` again implicitly references a group ID field. We select the name and the population count of the biggest and smallest city with calls to the `last(…)` and `first(...)` operators, respectively, in the `project` operation. +. Select the `state` field from the previous `group` operation. Note that `state` again implicitly references a group ID field. Because we do not want an implicitly generated ID to appear, we exclude the ID from the previous operation by using `and(previousOperation()).exclude()`. Because we want to populate the nested `City` structures in our output class, we have to emit appropriate sub-documents by using the nested method. +. Sort the resulting list of `StateStats` by their state name in ascending order in the `sort` operation. + +Note that we derive the name of the input collection from the `ZipInfo` class passed as the first parameter to the `newAggregation` method. + +[[mongo.aggregation.examples.example3]] +===== Aggregation Framework Example 3 + +This example is based on the https://docs.mongodb.org/manual/tutorial/aggregation-examples/#states-with-populations-over-10-million[States with Populations Over 10 Million] example from the MongoDB Aggregation Framework documentation. We added additional sorting to produce stable results with different MongoDB versions. Here we want to return all states with a population greater than 10 million, using the aggregation framework. This example demonstrates grouping, sorting, and matching (filtering). + +[source,java] +---- +class StateStats { + @Id String id; + String state; + @Field("totalPop") int totalPopulation; +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +TypedAggregation agg = newAggregation(ZipInfo.class, + group("state").sum("population").as("totalPop"), + sort(ASC, previousOperation(), "totalPop"), + match(where("totalPop").gte(10 * 1000 * 1000)) +); + +AggregationResults result = mongoTemplate.aggregate(agg, StateStats.class); +List stateStatsList = result.getMappedResults(); +---- + +The preceding listings use the following algorithm: + +. Group the input collection by the `state` field and calculate the sum of the `population` field and store the result in the new field `"totalPop"`. +. Sort the intermediate result by the id-reference of the previous group operation in addition to the `"totalPop"` field in ascending order. +. Filter the intermediate result by using a `match` operation which accepts a `Criteria` query as an argument. + +Note that we derive the name of the input collection from the `ZipInfo` class passed as first parameter to the `newAggregation` method. + +[[mongo.aggregation.examples.example4]] +===== Aggregation Framework Example 4 + +This example demonstrates the use of simple arithmetic operations in the projection operation. + +[source,java] +---- +class Product { + String id; + String name; + double netPrice; + int spaceUnits; +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +TypedAggregation agg = newAggregation(Product.class, + project("name", "netPrice") + .and("netPrice").plus(1).as("netPricePlus1") + .and("netPrice").minus(1).as("netPriceMinus1") + .and("netPrice").multiply(1.19).as("grossPrice") + .and("netPrice").divide(2).as("netPriceDiv2") + .and("spaceUnits").mod(2).as("spaceUnitsMod2") +); + +AggregationResults result = mongoTemplate.aggregate(agg, Document.class); +List resultList = result.getMappedResults(); +---- + +Note that we derive the name of the input collection from the `Product` class passed as first parameter to the `newAggregation` method. + +[[mongo.aggregation.examples.example5]] +===== Aggregation Framework Example 5 + +This example demonstrates the use of simple arithmetic operations derived from SpEL Expressions in the projection operation. + +[source,java] +---- +class Product { + String id; + String name; + double netPrice; + int spaceUnits; +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +TypedAggregation agg = newAggregation(Product.class, + project("name", "netPrice") + .andExpression("netPrice + 1").as("netPricePlus1") + .andExpression("netPrice - 1").as("netPriceMinus1") + .andExpression("netPrice / 2").as("netPriceDiv2") + .andExpression("netPrice * 1.19").as("grossPrice") + .andExpression("spaceUnits % 2").as("spaceUnitsMod2") + .andExpression("(netPrice * 0.8 + 1.2) * 1.19").as("grossPriceIncludingDiscountAndCharge") + +); + +AggregationResults result = mongoTemplate.aggregate(agg, Document.class); +List resultList = result.getMappedResults(); +---- + +[[mongo.aggregation.examples.example6]] +===== Aggregation Framework Example 6 + +This example demonstrates the use of complex arithmetic operations derived from SpEL Expressions in the projection operation. + +Note: The additional parameters passed to the `addExpression` method can be referenced with indexer expressions according to their position. In this example, we reference the first parameter of the parameters array with `[0]`. When the SpEL expression is transformed into a MongoDB aggregation framework expression, external parameter expressions are replaced with their respective values. + +[source,java] +---- +class Product { + String id; + String name; + double netPrice; + int spaceUnits; +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +double shippingCosts = 1.2; + +TypedAggregation agg = newAggregation(Product.class, + project("name", "netPrice") + .andExpression("(netPrice * (1-discountRate) + [0]) * (1+taxRate)", shippingCosts).as("salesPrice") +); + +AggregationResults result = mongoTemplate.aggregate(agg, Document.class); +List resultList = result.getMappedResults(); +---- + +Note that we can also refer to other fields of the document within the SpEL expression. + +[[mongo.aggregation.examples.example7]] +===== Aggregation Framework Example 7 + +This example uses conditional projection. It is derived from the https://docs.mongodb.com/manual/reference/operator/aggregation/cond/[$cond reference documentation]. + +[source,java] +---- +public class InventoryItem { + + @Id int id; + String item; + String description; + int qty; +} + +public class InventoryItemProjection { + + @Id int id; + String item; + String description; + int qty; + int discount +} +---- + +[source,java] +---- +import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; + +TypedAggregation agg = newAggregation(InventoryItem.class, + project("item").and("discount") + .applyCondition(ConditionalOperator.newBuilder().when(Criteria.where("qty").gte(250)) + .then(30) + .otherwise(20)) + .and(ifNull("description", "Unspecified")).as("description") +); + +AggregationResults result = mongoTemplate.aggregate(agg, "inventory", InventoryItemProjection.class); +List stateStatsList = result.getMappedResults(); +---- + +This one-step aggregation uses a projection operation with the `inventory` collection. We project the `discount` field by using a conditional operation for all inventory items that have a `qty` greater than or equal to `250`. A second conditional projection is performed for the `description` field. We apply the `Unspecified` description to all items that either do not have a `description` field or items that have a `null` description. + +As of MongoDB 3.6, it is possible to exclude fields from the projection by using a conditional expression. + +.Conditional aggregation projection +==== +[source,java] +---- +TypedAggregation agg = Aggregation.newAggregation(Book.class, + project("title") + .and(ConditionalOperators.when(ComparisonOperators.valueOf("author.middle") <1> + .equalToValue("")) <2> + .then("$$REMOVE") <3> + .otherwiseValueOf("author.middle") <4> + ) + .as("author.middle")); +---- +<1> If the value of the field `author.middle` +<2> does not contain a value, +<3> then use https://docs.mongodb.com/manual/reference/aggregation-variables/#variable.REMOVE[``$$REMOVE``] to exclude the field. +<4> Otherwise, add the field value of `author.middle`. +==== diff --git a/src/main/asciidoc/reference/gridfs.adoc b/src/main/asciidoc/reference/gridfs.adoc new file mode 100644 index 0000000000..94caf11f47 --- /dev/null +++ b/src/main/asciidoc/reference/gridfs.adoc @@ -0,0 +1,115 @@ +[[gridfs]] +== GridFS Support + +MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a `GridFsOperations` interface as well as the corresponding implementation, `GridFsTemplate`, to let you interact with the filesystem. You can set up a `GridFsTemplate` instance by handing it a `MongoDatabaseFactory` as well as a `MongoConverter`, as the following example shows: + +.JavaConfig setup for a GridFsTemplate +==== +[source,java] +---- +class GridFsConfiguration extends AbstractMongoClientConfiguration { + + // … further configuration omitted + + @Bean + public GridFsTemplate gridFsTemplate() { + return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter()); + } +} +---- +==== + +The corresponding XML configuration follows: + +.XML configuration for a GridFsTemplate +==== +[source,xml] +---- + + + + + + + + + + + + +---- +==== + +The template can now be injected and used to perform storage and retrieval operations, as the following example shows: + +.Using GridFsTemplate to store files +==== +[source,java] +---- +class GridFsClient { + + @Autowired + GridFsOperations operations; + + @Test + public void storeFileToGridFs() { + + FileMetadata metadata = new FileMetadata(); + // populate metadata + Resource file = … // lookup File or Resource + + operations.store(file.getInputStream(), "filename.txt", metadata); + } +} +---- +==== + +The `store(…)` operations take an `InputStream`, a filename, and (optionally) metadata information about the file to store. The metadata can be an arbitrary object, which will be marshaled by the `MongoConverter` configured with the `GridFsTemplate`. Alternatively, you can also provide a `Document`. + +You can read files from the filesystem through either the `find(…)` or the `getResources(…)` methods. Let's have a look at the `find(…)` methods first. You can either find a single file or multiple files that match a `Query`. You can use the `GridFsCriteria` helper class to define queries. It provides static factory methods to encapsulate default metadata fields (such as `whereFilename()` and `whereContentType()`) or a custom one through `whereMetaData()`. The following example shows how to use `GridFsTemplate` to query for files: + +.Using GridFsTemplate to query for files +==== +[source,java] +---- +class GridFsClient { + + @Autowired + GridFsOperations operations; + + @Test + public void findFilesInGridFs() { + GridFSFindIterable result = operations.find(query(whereFilename().is("filename.txt"))) + } +} +---- +==== + +NOTE: Currently, MongoDB does not support defining sort criteria when retrieving files from GridFS. For this reason, any sort criteria defined on the `Query` instance handed into the `find(…)` method are disregarded. + +The other option to read files from the GridFs is to use the methods introduced by the `ResourcePatternResolver` interface. They allow handing an Ant path into the method and can thus retrieve files matching the given pattern. The following example shows how to use `GridFsTemplate` to read files: + +.Using GridFsTemplate to read files +==== +[source,java] +---- +class GridFsClient { + + @Autowired + GridFsOperations operations; + + @Test + public void readFilesFromGridFs() { + GridFsResources[] txtFiles = operations.getResources("*.txt"); + } +} +---- +==== + +`GridFsOperations` extends `ResourcePatternResolver` and lets the `GridFsTemplate` (for example) to be plugged into an `ApplicationContext` to read Spring Config files from MongoDB database. diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index daaad49963..f214edba4c 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -1002,7 +1002,7 @@ assertThat(upserted.getFirstName()).isEqualTo("Mary"); assertThat(upserted.getAge()).isOne(); ---- -= [[mongo-template.aggregation-update]] +[[mongo-template.aggregation-update]] === Aggregation Pipeline Updates Update methods exposed by `MongoOperations` and `ReactiveMongoOperations` also accept an <> via `AggregationUpdate`. @@ -2419,662 +2419,7 @@ GroupByResults results = mongoTemplate.group(where("x").gt(0), keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }").reduceFunction("classpath:groupReduce.js"), XObject.class); ---- -[[mongo.aggregation]] -== Aggregation Framework Support - -Spring Data MongoDB provides support for the Aggregation Framework introduced to MongoDB in version 2.2. - -For further information, see the full https://docs.mongodb.org/manual/aggregation/[reference documentation] of the aggregation framework and other data aggregation tools for MongoDB. - -[[mongo.aggregation.basic-concepts]] -=== Basic Concepts - -The Aggregation Framework support in Spring Data MongoDB is based on the following key abstractions: `Aggregation`, `AggregationDefinition`, and `AggregationResults`. - -* `Aggregation` -+ -An `Aggregation` represents a MongoDB `aggregate` operation and holds the description of the aggregation pipeline instructions. Aggregations are created by invoking the appropriate `newAggregation(…)` static factory method of the `Aggregation` class, which takes a list of `AggregateOperation` and an optional input class. -+ -The actual aggregate operation is run by the `aggregate` method of the `MongoTemplate`, which takes the desired output class as a parameter. -+ -* `TypedAggregation` -+ -A `TypedAggregation`, just like an `Aggregation`, holds the instructions of the aggregation pipeline and a reference to the input type, that is used for mapping domain properties to actual document fields. -+ -At runtime, field references get checked against the given input type, considering potential `@Field` annotations. -[NOTE] -==== -Changed in 3.2 referencing non-existent properties does no longer raise errors. To restore the previous behaviour use the `strictMapping` option of `AggregationOptions`. -==== -* `AggregationDefinition` -+ -An `AggregationDefinition` represents a MongoDB aggregation pipeline operation and describes the processing that should be performed in this aggregation step. Although you could manually create an `AggregationDefinition`, we recommend using the static factory methods provided by the `Aggregate` class to construct an `AggregateOperation`. -+ -* `AggregationResults` -+ -`AggregationResults` is the container for the result of an aggregate operation. It provides access to the raw aggregation result, in the form of a `Document` to the mapped objects and other information about the aggregation. -+ -The following listing shows the canonical example for using the Spring Data MongoDB support for the MongoDB Aggregation Framework: -+ -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -Aggregation agg = newAggregation( - pipelineOP1(), - pipelineOP2(), - pipelineOPn() -); - -AggregationResults results = mongoTemplate.aggregate(agg, "INPUT_COLLECTION_NAME", OutputType.class); -List mappedResult = results.getMappedResults(); ----- - -Note that, if you provide an input class as the first parameter to the `newAggregation` method, the `MongoTemplate` derives the name of the input collection from this class. Otherwise, if you do not not specify an input class, you must provide the name of the input collection explicitly. If both an input class and an input collection are provided, the latter takes precedence. - -[[mongo.aggregation.supported-aggregation-operations]] -=== Supported Aggregation Operations - -The MongoDB Aggregation Framework provides the following types of aggregation operations: - -* Pipeline Aggregation Operators -* Group Aggregation Operators -* Boolean Aggregation Operators -* Comparison Aggregation Operators -* Arithmetic Aggregation Operators -* String Aggregation Operators -* Date Aggregation Operators -* Array Aggregation Operators -* Conditional Aggregation Operators -* Lookup Aggregation Operators -* Convert Aggregation Operators -* Object Aggregation Operators -* Script Aggregation Operators - -At the time of this writing, we provide support for the following Aggregation Operations in Spring Data MongoDB: - -.Aggregation Operations currently supported by Spring Data MongoDB -[cols="2*"] -|=== -| Pipeline Aggregation Operators -| `bucket`, `bucketAuto`, `count`, `facet`, `geoNear`, `graphLookup`, `group`, `limit`, `lookup`, `match`, `project`, `replaceRoot`, `skip`, `sort`, `unwind` - -| Set Aggregation Operators -| `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue` - -| Group/Accumulator Aggregation Operators -| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` - -| Arithmetic Aggregation Operators -| `abs`, `add` (via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` - -| Document Operators -| `rank`, `denseRank`, `documentNumber`, `shift` - -| String Aggregation Operators -| `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` - -| Comparison Aggregation Operators -| `eq` (via: `is`), `gt`, `gte`, `lt`, `lte`, `ne` - -| Array Aggregation Operators -| `arrayElementAt`, `arrayToObject`, `concatArrays`, `filter`, `in`, `indexOfArray`, `isArray`, `range`, `reverseArray`, `reduce`, `size`, `slice`, `zip` - -| Literal Operators -| `literal` - -| Date Aggregation Operators -| `dayOfYear`, `dayOfMonth`, `dayOfWeek`, `year`, `month`, `week`, `hour`, `minute`, `second`, `millisecond`, `dateToString`, `dateFromString`, `dateFromParts`, `dateToParts`, `isoDayOfWeek`, `isoWeek`, `isoWeekYear` - -| Variable Operators -| `map` - -| Conditional Aggregation Operators -| `cond`, `ifNull`, `switch` - -| Type Aggregation Operators -| `type` - -| Convert Aggregation Operators -| `convert`, `toBool`, `toDate`, `toDecimal`, `toDouble`, `toInt`, `toLong`, `toObjectId`, `toString` - -| Object Aggregation Operators -| `objectToArray`, `mergeObjects` - -| Script Aggregation Operators -| `function`, `accumulator` -|=== - -* The operation is mapped or added by Spring Data MongoDB. - -Note that the aggregation operations not listed here are currently not supported by Spring Data MongoDB.Comparison aggregation operators are expressed as `Criteria` expressions. - -[[mongo.aggregation.projection]] -=== Projection Expressions - -Projection expressions are used to define the fields that are the outcome of a particular aggregation step. Projection expressions can be defined through the `project` method of the `Aggregation` class, either by passing a list of `String` objects or an aggregation framework `Fields` object. The projection can be extended with additional fields through a fluent API by using the `and(String)` method and aliased by using the `as(String)` method. -Note that you can also define fields with aliases by using the `Fields.field` static factory method of the aggregation framework, which you can then use to construct a new `Fields` instance. References to projected fields in later aggregation stages are valid only for the field names of included fields or their aliases (including newly defined fields and their aliases). Fields not included in the projection cannot be referenced in later aggregation stages. The following listings show examples of projection expression: - -.Projection expression examples -==== -[source,java] ----- -// generates {$project: {name: 1, netPrice: 1}} -project("name", "netPrice") - -// generates {$project: {thing1: $thing2}} -project().and("thing1").as("thing2") - -// generates {$project: {a: 1, b: 1, thing2: $thing1}} -project("a","b").and("thing1").as("thing2") ----- -==== - -.Multi-Stage Aggregation using Projection and Sorting -==== -[source,java] ----- -// generates {$project: {name: 1, netPrice: 1}}, {$sort: {name: 1}} -project("name", "netPrice"), sort(ASC, "name") - -// generates {$project: {name: $firstname}}, {$sort: {name: 1}} -project().and("firstname").as("name"), sort(ASC, "name") - -// does not work -project().and("firstname").as("name"), sort(ASC, "firstname") ----- -==== - -More examples for project operations can be found in the `AggregationTests` class. Note that further details regarding the projection expressions can be found in the https://docs.mongodb.org/manual/reference/operator/aggregation/project/#pipe._S_project[corresponding section] of the MongoDB Aggregation Framework reference documentation. - -[[mongo.aggregation.facet]] -=== Faceted Classification - -As of Version 3.4, MongoDB supports faceted classification by using the Aggregation Framework. A faceted classification uses semantic categories (either general or subject-specific) that are combined to create the full classification entry. Documents flowing through the aggregation pipeline are classified into buckets. A multi-faceted classification enables various aggregations on the same set of input documents, without needing to retrieve the input documents multiple times. - -==== Buckets - -Bucket operations categorize incoming documents into groups, called buckets, based on a specified expression and bucket boundaries. Bucket operations require a grouping field or a grouping expression. You can define them by using the `bucket()` and `bucketAuto()` methods of the `Aggregate` class. `BucketOperation` and `BucketAutoOperation` can expose accumulations based on aggregation expressions for input documents. You can extend the bucket operation with additional parameters through a fluent API by using the `with…()` methods and the `andOutput(String)` method. You can alias the operation by using the `as(String)` method. Each bucket is represented as a document in the output. - -`BucketOperation` takes a defined set of boundaries to group incoming documents into these categories. Boundaries are required to be sorted. The following listing shows some examples of bucket operations: - -.Bucket operation examples -==== -[source,java] ----- -// generates {$bucket: {groupBy: $price, boundaries: [0, 100, 400]}} -bucket("price").withBoundaries(0, 100, 400); - -// generates {$bucket: {groupBy: $price, default: "Other" boundaries: [0, 100]}} -bucket("price").withBoundaries(0, 100).withDefault("Other"); - -// generates {$bucket: {groupBy: $price, boundaries: [0, 100], output: { count: { $sum: 1}}}} -bucket("price").withBoundaries(0, 100).andOutputCount().as("count"); - -// generates {$bucket: {groupBy: $price, boundaries: [0, 100], 5, output: { titles: { $push: "$title"}}} -bucket("price").withBoundaries(0, 100).andOutput("title").push().as("titles"); ----- -==== - -`BucketAutoOperation` determines boundaries in an attempt to evenly distribute documents into a specified number of buckets. `BucketAutoOperation` optionally takes a granularity value that specifies the https://en.wikipedia.org/wiki/Preferred_number[preferred number] series to use to ensure that the calculated boundary edges end on preferred round numbers or on powers of 10. The following listing shows examples of bucket operations: - -.Bucket operation examples -==== -[source,java] ----- -// generates {$bucketAuto: {groupBy: $price, buckets: 5}} -bucketAuto("price", 5) - -// generates {$bucketAuto: {groupBy: $price, buckets: 5, granularity: "E24"}} -bucketAuto("price", 5).withGranularity(Granularities.E24).withDefault("Other"); - -// generates {$bucketAuto: {groupBy: $price, buckets: 5, output: { titles: { $push: "$title"}}} -bucketAuto("price", 5).andOutput("title").push().as("titles"); ----- -==== - -To create output fields in buckets, bucket operations can use `AggregationExpression` through `andOutput()` and <> through `andOutputExpression()`. - -Note that further details regarding bucket expressions can be found in the https://docs.mongodb.org/manual/reference/operator/aggregation/bucket/[`$bucket` section] and -https://docs.mongodb.org/manual/reference/operator/aggregation/bucketAuto/[`$bucketAuto` section] of the MongoDB Aggregation Framework reference documentation. - -==== Multi-faceted Aggregation - -Multiple aggregation pipelines can be used to create multi-faceted aggregations that characterize data across multiple dimensions (or facets) within a single aggregation stage. Multi-faceted aggregations provide multiple filters and categorizations to guide data browsing and analysis. A common implementation of faceting is how many online retailers provide ways to narrow down search results by applying filters on product price, manufacturer, size, and other factors. - -You can define a `FacetOperation` by using the `facet()` method of the `Aggregation` class. You can customize it with multiple aggregation pipelines by using the `and()` method. Each sub-pipeline has its own field in the output document where its results are stored as an array of documents. - -Sub-pipelines can project and filter input documents prior to grouping. Common use cases include extraction of date parts or calculations before categorization. The following listing shows facet operation examples: - -.Facet operation examples -==== -[source,java] ----- -// generates {$facet: {categorizedByPrice: [ { $match: { price: {$exists : true}}}, { $bucketAuto: {groupBy: $price, buckets: 5}}]}} -facet(match(Criteria.where("price").exists(true)), bucketAuto("price", 5)).as("categorizedByPrice")) - -// generates {$facet: {categorizedByCountry: [ { $match: { country: {$exists : true}}}, { $sortByCount: "$country"}]}} -facet(match(Criteria.where("country").exists(true)), sortByCount("country")).as("categorizedByCountry")) - -// generates {$facet: {categorizedByYear: [ -// { $project: { title: 1, publicationYear: { $year: "publicationDate"}}}, -// { $bucketAuto: {groupBy: $price, buckets: 5, output: { titles: {$push:"$title"}}} -// ]}} -facet(project("title").and("publicationDate").extractYear().as("publicationYear"), - bucketAuto("publicationYear", 5).andOutput("title").push().as("titles")) - .as("categorizedByYear")) ----- -==== - -Note that further details regarding facet operation can be found in the https://docs.mongodb.org/manual/reference/operator/aggregation/facet/[`$facet` section] of the MongoDB Aggregation Framework reference documentation. - -[[mongo.aggregation.sort-by-count]] -==== Sort By Count - -Sort by count operations group incoming documents based on the value of a specified expression, compute the count of documents in each distinct group, and sort the results by count. It offers a handy shortcut to apply sorting when using <>. Sort by count operations require a grouping field or grouping expression. The following listing shows a sort by count example: - -.Sort by count example -==== -[source,java] ----- -// generates { $sortByCount: "$country" } -sortByCount("country"); ----- -==== - -A sort by count operation is equivalent to the following BSON (Binary JSON): - ----- -{ $group: { _id: , count: { $sum: 1 } } }, -{ $sort: { count: -1 } } ----- - -[[mongo.aggregation.projection.expressions]] -==== Spring Expression Support in Projection Expressions - -We support the use of SpEL expressions in projection expressions through the `andExpression` method of the `ProjectionOperation` and `BucketOperation` classes. This feature lets you define the desired expression as a SpEL expression. On running a query, the SpEL expression is translated into a corresponding MongoDB projection expression part. This arrangement makes it much easier to express complex calculations. - -===== Complex Calculations with SpEL expressions - -Consider the following SpEL expression: - -[source,java] ----- -1 + (q + 1) / (q - 1) ----- - -The preceding expression is translated into the following projection expression part: - -[source,javascript] ----- -{ "$add" : [ 1, { - "$divide" : [ { - "$add":["$q", 1]}, { - "$subtract":[ "$q", 1]} - ] -}]} ----- - -You can see examples in more context in <> and <>. You can find more usage examples for supported SpEL expression constructs in `SpelExpressionTransformerUnitTests`. The following table shows the SpEL transformations supported by Spring Data MongoDB: - -.Supported SpEL transformations -[%header,cols="2"] -|=== -| SpEL Expression -| Mongo Expression Part -| a == b -| { $eq : [$a, $b] } -| a != b -| { $ne : [$a , $b] } -| a > b -| { $gt : [$a, $b] } -| a >= b -| { $gte : [$a, $b] } -| a < b -| { $lt : [$a, $b] } -| a <= b -| { $lte : [$a, $b] } -| a + b -| { $add : [$a, $b] } -| a - b -| { $subtract : [$a, $b] } -| a * b -| { $multiply : [$a, $b] } -| a / b -| { $divide : [$a, $b] } -| a^b -| { $pow : [$a, $b] } -| a % b -| { $mod : [$a, $b] } -| a && b -| { $and : [$a, $b] } -| a \|\| b -| { $or : [$a, $b] } -| !a -| { $not : [$a] } -|=== - -In addition to the transformations shown in the preceding table, you can use standard SpEL operations such as `new` to (for example) create arrays and reference expressions through their names (followed by the arguments to use in brackets). The following example shows how to create an array in this fashion: - -[source,java] ----- -// { $setEquals : [$a, [5, 8, 13] ] } -.andExpression("setEquals(a, new int[]{5, 8, 13})"); ----- - -[[mongo.aggregation.examples]] -==== Aggregation Framework Examples - -The examples in this section demonstrate the usage patterns for the MongoDB Aggregation Framework with Spring Data MongoDB. - -[[mongo.aggregation.examples.example1]] -===== Aggregation Framework Example 1 - -In this introductory example, we want to aggregate a list of tags to get the occurrence count of a particular tag from a MongoDB collection (called `tags`) sorted by the occurrence count in descending order. This example demonstrates the usage of grouping, sorting, projections (selection), and unwinding (result splitting). - -[source,java] ----- -class TagCount { - String tag; - int n; -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -Aggregation agg = newAggregation( - project("tags"), - unwind("tags"), - group("tags").count().as("n"), - project("n").and("tag").previousOperation(), - sort(DESC, "n") -); - -AggregationResults results = mongoTemplate.aggregate(agg, "tags", TagCount.class); -List tagCount = results.getMappedResults(); ----- - -The preceding listing uses the following algorithm: - -. Create a new aggregation by using the `newAggregation` static factory method, to which we pass a list of aggregation operations. These aggregate operations define the aggregation pipeline of our `Aggregation`. -. Use the `project` operation to select the `tags` field (which is an array of strings) from the input collection. -. Use the `unwind` operation to generate a new document for each tag within the `tags` array. -. Use the `group` operation to define a group for each `tags` value for which we aggregate the occurrence count (by using the `count` aggregation operator and collecting the result in a new field called `n`). -. Select the `n` field and create an alias for the ID field generated from the previous group operation (hence the call to `previousOperation()`) with a name of `tag`. -. Use the `sort` operation to sort the resulting list of tags by their occurrence count in descending order. -. Call the `aggregate` method on `MongoTemplate` to let MongoDB perform the actual aggregation operation, with the created `Aggregation` as an argument. - -Note that the input collection is explicitly specified as the `tags` parameter to the `aggregate` Method. If the name of the input collection is not specified explicitly, it is derived from the input class passed as the first parameter to the `newAggreation` method. - -[[mongo.aggregation.examples.example2]] -===== Aggregation Framework Example 2 - -This example is based on the https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state[Largest and Smallest Cities by State] example from the MongoDB Aggregation Framework documentation. We added additional sorting to produce stable results with different MongoDB versions. Here we want to return the smallest and largest cities by population for each state by using the aggregation framework. This example demonstrates grouping, sorting, and projections (selection). - -[source,java] ----- -class ZipInfo { - String id; - String city; - String state; - @Field("pop") int population; - @Field("loc") double[] location; -} - -class City { - String name; - int population; -} - -class ZipInfoStats { - String id; - String state; - City biggestCity; - City smallestCity; -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -TypedAggregation aggregation = newAggregation(ZipInfo.class, - group("state", "city") - .sum("population").as("pop"), - sort(ASC, "pop", "state", "city"), - group("state") - .last("city").as("biggestCity") - .last("pop").as("biggestPop") - .first("city").as("smallestCity") - .first("pop").as("smallestPop"), - project() - .and("state").previousOperation() - .and("biggestCity") - .nested(bind("name", "biggestCity").and("population", "biggestPop")) - .and("smallestCity") - .nested(bind("name", "smallestCity").and("population", "smallestPop")), - sort(ASC, "state") -); - -AggregationResults result = mongoTemplate.aggregate(aggregation, ZipInfoStats.class); -ZipInfoStats firstZipInfoStats = result.getMappedResults().get(0); ----- - -Note that the `ZipInfo` class maps the structure of the given input-collection. The `ZipInfoStats` class defines the structure in the desired output format. - -The preceding listings use the following algorithm: - -. Use the `group` operation to define a group from the input-collection. The grouping criteria is the combination of the `state` and `city` fields, which forms the ID structure of the group. We aggregate the value of the `population` property from the grouped elements by using the `sum` operator and save the result in the `pop` field. -. Use the `sort` operation to sort the intermediate-result by the `pop`, `state` and `city` fields, in ascending order, such that the smallest city is at the top and the biggest city is at the bottom of the result. Note that the sorting on `state` and `city` is implicitly performed against the group ID fields (which Spring Data MongoDB handled). -. Use a `group` operation again to group the intermediate result by `state`. Note that `state` again implicitly references a group ID field. We select the name and the population count of the biggest and smallest city with calls to the `last(…)` and `first(...)` operators, respectively, in the `project` operation. -. Select the `state` field from the previous `group` operation. Note that `state` again implicitly references a group ID field. Because we do not want an implicitly generated ID to appear, we exclude the ID from the previous operation by using `and(previousOperation()).exclude()`. Because we want to populate the nested `City` structures in our output class, we have to emit appropriate sub-documents by using the nested method. -. Sort the resulting list of `StateStats` by their state name in ascending order in the `sort` operation. - -Note that we derive the name of the input collection from the `ZipInfo` class passed as the first parameter to the `newAggregation` method. - -[[mongo.aggregation.examples.example3]] -===== Aggregation Framework Example 3 - -This example is based on the https://docs.mongodb.org/manual/tutorial/aggregation-examples/#states-with-populations-over-10-million[States with Populations Over 10 Million] example from the MongoDB Aggregation Framework documentation. We added additional sorting to produce stable results with different MongoDB versions. Here we want to return all states with a population greater than 10 million, using the aggregation framework. This example demonstrates grouping, sorting, and matching (filtering). - -[source,java] ----- -class StateStats { - @Id String id; - String state; - @Field("totalPop") int totalPopulation; -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -TypedAggregation agg = newAggregation(ZipInfo.class, - group("state").sum("population").as("totalPop"), - sort(ASC, previousOperation(), "totalPop"), - match(where("totalPop").gte(10 * 1000 * 1000)) -); - -AggregationResults result = mongoTemplate.aggregate(agg, StateStats.class); -List stateStatsList = result.getMappedResults(); ----- - -The preceding listings use the following algorithm: - -. Group the input collection by the `state` field and calculate the sum of the `population` field and store the result in the new field `"totalPop"`. -. Sort the intermediate result by the id-reference of the previous group operation in addition to the `"totalPop"` field in ascending order. -. Filter the intermediate result by using a `match` operation which accepts a `Criteria` query as an argument. - -Note that we derive the name of the input collection from the `ZipInfo` class passed as first parameter to the `newAggregation` method. - -[[mongo.aggregation.examples.example4]] -===== Aggregation Framework Example 4 - -This example demonstrates the use of simple arithmetic operations in the projection operation. - -[source,java] ----- -class Product { - String id; - String name; - double netPrice; - int spaceUnits; -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -TypedAggregation agg = newAggregation(Product.class, - project("name", "netPrice") - .and("netPrice").plus(1).as("netPricePlus1") - .and("netPrice").minus(1).as("netPriceMinus1") - .and("netPrice").multiply(1.19).as("grossPrice") - .and("netPrice").divide(2).as("netPriceDiv2") - .and("spaceUnits").mod(2).as("spaceUnitsMod2") -); - -AggregationResults result = mongoTemplate.aggregate(agg, Document.class); -List resultList = result.getMappedResults(); ----- - -Note that we derive the name of the input collection from the `Product` class passed as first parameter to the `newAggregation` method. - -[[mongo.aggregation.examples.example5]] -===== Aggregation Framework Example 5 - -This example demonstrates the use of simple arithmetic operations derived from SpEL Expressions in the projection operation. - -[source,java] ----- -class Product { - String id; - String name; - double netPrice; - int spaceUnits; -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -TypedAggregation agg = newAggregation(Product.class, - project("name", "netPrice") - .andExpression("netPrice + 1").as("netPricePlus1") - .andExpression("netPrice - 1").as("netPriceMinus1") - .andExpression("netPrice / 2").as("netPriceDiv2") - .andExpression("netPrice * 1.19").as("grossPrice") - .andExpression("spaceUnits % 2").as("spaceUnitsMod2") - .andExpression("(netPrice * 0.8 + 1.2) * 1.19").as("grossPriceIncludingDiscountAndCharge") - -); - -AggregationResults result = mongoTemplate.aggregate(agg, Document.class); -List resultList = result.getMappedResults(); ----- - -[[mongo.aggregation.examples.example6]] -===== Aggregation Framework Example 6 - -This example demonstrates the use of complex arithmetic operations derived from SpEL Expressions in the projection operation. - -Note: The additional parameters passed to the `addExpression` method can be referenced with indexer expressions according to their position. In this example, we reference the first parameter of the parameters array with `[0]`. When the SpEL expression is transformed into a MongoDB aggregation framework expression, external parameter expressions are replaced with their respective values. - -[source,java] ----- -class Product { - String id; - String name; - double netPrice; - int spaceUnits; -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -double shippingCosts = 1.2; - -TypedAggregation agg = newAggregation(Product.class, - project("name", "netPrice") - .andExpression("(netPrice * (1-discountRate) + [0]) * (1+taxRate)", shippingCosts).as("salesPrice") -); - -AggregationResults result = mongoTemplate.aggregate(agg, Document.class); -List resultList = result.getMappedResults(); ----- - -Note that we can also refer to other fields of the document within the SpEL expression. - -[[mongo.aggregation.examples.example7]] -===== Aggregation Framework Example 7 - -This example uses conditional projection. It is derived from the https://docs.mongodb.com/manual/reference/operator/aggregation/cond/[$cond reference documentation]. - -[source,java] ----- -public class InventoryItem { - - @Id int id; - String item; - String description; - int qty; -} - -public class InventoryItemProjection { - - @Id int id; - String item; - String description; - int qty; - int discount -} ----- - -[source,java] ----- -import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; - -TypedAggregation agg = newAggregation(InventoryItem.class, - project("item").and("discount") - .applyCondition(ConditionalOperator.newBuilder().when(Criteria.where("qty").gte(250)) - .then(30) - .otherwise(20)) - .and(ifNull("description", "Unspecified")).as("description") -); - -AggregationResults result = mongoTemplate.aggregate(agg, "inventory", InventoryItemProjection.class); -List stateStatsList = result.getMappedResults(); ----- - -This one-step aggregation uses a projection operation with the `inventory` collection. We project the `discount` field by using a conditional operation for all inventory items that have a `qty` greater than or equal to `250`. A second conditional projection is performed for the `description` field. We apply the `Unspecified` description to all items that either do not have a `description` field or items that have a `null` description. - -As of MongoDB 3.6, it is possible to exclude fields from the projection by using a conditional expression. - -.Conditional aggregation projection -==== -[source,java] ----- -TypedAggregation agg = Aggregation.newAggregation(Book.class, - project("title") - .and(ConditionalOperators.when(ComparisonOperators.valueOf("author.middle") <1> - .equalToValue("")) <2> - .then("$$REMOVE") <3> - .otherwiseValueOf("author.middle") <4> - ) - .as("author.middle")); ----- -<1> If the value of the field `author.middle` -<2> does not contain a value, -<3> then use https://docs.mongodb.com/manual/reference/aggregation-variables/#variable.REMOVE[``$$REMOVE``] to exclude the field. -<4> Otherwise, add the field value of `author.middle`. -==== +include::aggregation-framework.adoc[] [[mongo-template.index-and-collections]] == Index and Collection Management @@ -3267,122 +2612,7 @@ boolean hasIndex = template.execute("geolocation", new CollectionCallbackBoolean }); ---- -[[gridfs]] -== GridFS Support - -MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a `GridFsOperations` interface as well as the corresponding implementation, `GridFsTemplate`, to let you interact with the filesystem. You can set up a `GridFsTemplate` instance by handing it a `MongoDatabaseFactory` as well as a `MongoConverter`, as the following example shows: - -.JavaConfig setup for a GridFsTemplate -==== -[source,java] ----- -class GridFsConfiguration extends AbstractMongoClientConfiguration { - - // … further configuration omitted - - @Bean - public GridFsTemplate gridFsTemplate() { - return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter()); - } -} ----- -==== - -The corresponding XML configuration follows: - -.XML configuration for a GridFsTemplate -==== -[source,xml] ----- - - - - - - - - - - - - ----- -==== - -The template can now be injected and used to perform storage and retrieval operations, as the following example shows: - -.Using GridFsTemplate to store files -==== -[source,java] ----- -class GridFsClient { - - @Autowired - GridFsOperations operations; - - @Test - public void storeFileToGridFs() { - - FileMetadata metadata = new FileMetadata(); - // populate metadata - Resource file = … // lookup File or Resource - - operations.store(file.getInputStream(), "filename.txt", metadata); - } -} ----- -==== - -The `store(…)` operations take an `InputStream`, a filename, and (optionally) metadata information about the file to store. The metadata can be an arbitrary object, which will be marshaled by the `MongoConverter` configured with the `GridFsTemplate`. Alternatively, you can also provide a `Document`. - -You can read files from the filesystem through either the `find(…)` or the `getResources(…)` methods. Let's have a look at the `find(…)` methods first. You can either find a single file or multiple files that match a `Query`. You can use the `GridFsCriteria` helper class to define queries. It provides static factory methods to encapsulate default metadata fields (such as `whereFilename()` and `whereContentType()`) or a custom one through `whereMetaData()`. The following example shows how to use `GridFsTemplate` to query for files: - -.Using GridFsTemplate to query for files -==== -[source,java] ----- -class GridFsClient { - - @Autowired - GridFsOperations operations; - - @Test - public void findFilesInGridFs() { - GridFSFindIterable result = operations.find(query(whereFilename().is("filename.txt"))) - } -} ----- -==== - -NOTE: Currently, MongoDB does not support defining sort criteria when retrieving files from GridFS. For this reason, any sort criteria defined on the `Query` instance handed into the `find(…)` method are disregarded. - -The other option to read files from the GridFs is to use the methods introduced by the `ResourcePatternResolver` interface. They allow handing an Ant path into the method and can thus retrieve files matching the given pattern. The following example shows how to use `GridFsTemplate` to read files: - -.Using GridFsTemplate to read files -==== -[source,java] ----- -class GridFsClient { - - @Autowired - GridFsOperations operations; - - @Test - public void readFilesFromGridFs() { - GridFsResources[] txtFiles = operations.getResources("*.txt"); - } -} ----- -==== - -`GridFsOperations` extends `ResourcePatternResolver` and lets the `GridFsTemplate` (for example) to be plugged into an `ApplicationContext` to read Spring Config files from MongoDB database. - +include::gridfs.adoc[] include::tailable-cursors.adoc[] include::change-streams.adoc[] include::time-series.adoc[] From 75b5a548b61c3ea1fa70bb60cdc69ff6ee2c91c6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 11:23:42 +0200 Subject: [PATCH 0494/1381] Polishing. Fix asterisk callouts. See #3786 --- .../asciidoc/reference/aggregation-framework.adoc | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index a843af17f4..547b3b1530 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -57,7 +57,7 @@ Note that, if you provide an input class as the first parameter to the `newAggre The MongoDB Aggregation Framework provides the following types of aggregation operations: * Pipeline Aggregation Operators -* Group Aggregation Operators +* Group/Accumulator Aggregation Operators * Boolean Aggregation Operators * Comparison Aggregation Operators * Arithmetic Aggregation Operators @@ -82,19 +82,16 @@ At the time of this writing, we provide support for the following Aggregation Op | `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue` | Group/Accumulator Aggregation Operators -| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `(*count)`, `stdDevPop`, `stdDevSamp` +| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (*via `minus`), `trunc` - -| Document Operators -| `rank`, `denseRank`, `documentNumber`, `shift` +| `abs`, `add` (+++*+++ via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` | Comparison Aggregation Operators -| `eq` (via: `is`), `gt`, `gte`, `lt`, `lte`, `ne` +| `eq` (+++*+++ via `is`), `gt`, `gte`, `lt`, `lte`, `ne` | Array Aggregation Operators | `arrayElementAt`, `arrayToObject`, `concatArrays`, `filter`, `in`, `indexOfArray`, `isArray`, `range`, `reverseArray`, `reduce`, `size`, `slice`, `zip` @@ -124,9 +121,9 @@ At the time of this writing, we provide support for the following Aggregation Op | `function`, `accumulator` |=== -* The operation is mapped or added by Spring Data MongoDB. ++++*+++ The operation is mapped or added by Spring Data MongoDB. -Note that the aggregation operations not listed here are currently not supported by Spring Data MongoDB.Comparison aggregation operators are expressed as `Criteria` expressions. +Note that the aggregation operations not listed here are currently not supported by Spring Data MongoDB. Comparison aggregation operators are expressed as `Criteria` expressions. [[mongo.aggregation.projection]] === Projection Expressions From 82b33331fcc998cbd29421e9a6f1d59f3a7fd0a2 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 22 Jul 2021 14:08:06 +0200 Subject: [PATCH 0495/1381] Add support for `$derivative` aggregation operator. Closes: #3716 Original pull request: #3742. --- .../core/aggregation/ArithmeticOperators.java | 55 +++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 1 + .../ArithmeticOperatorsUnitTests.java | 7 +++ .../SpelExpressionTransformerUnitTests.java | 5 ++ 4 files changed, 68 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index b27e54d298..fe54f2434e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -26,7 +26,9 @@ import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevPop; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevSamp; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Sum; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Gateway to {@literal Arithmetic} aggregation operations that perform math operations on numbers. @@ -591,6 +593,31 @@ public Round roundToPlace(int place) { return round().place(place); } + /** + * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. + * + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Derivative derivative() { + return derivative(null); + } + + /** + * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. + * + * @param unit The time unit ({@literal week, day, hour, minute, second, millisecond}) to apply can be + * {@literal null}. + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Derivative derivative(@Nullable String unit) { + + Derivative derivative = usesFieldRef() ? Derivative.derivativeOf(fieldReference) + : Derivative.derivativeOf(expression); + return StringUtils.hasText(unit) ? derivative.unit(unit) : derivative; + } + private boolean usesFieldRef() { return fieldReference != null; } @@ -1724,4 +1751,32 @@ protected String getMongoMethod() { return "$round"; } } + + public static class Derivative extends AbstractAggregationExpression { + + private Derivative(Object value) { + super(value); + } + + public static Derivative derivativeOf(String fieldReference) { + return new Derivative(Collections.singletonMap("input", Fields.field(fieldReference))); + } + + public static Derivative derivativeOf(AggregationExpression expression) { + return new Derivative(Collections.singletonMap("input", expression)); + } + + public static Derivative derivativeOfValue(Number value) { + return new Derivative(Collections.singletonMap("input", value)); + } + + public Derivative unit(String unit) { + return new Derivative(append("unit", unit)); + } + + @Override + protected String getMongoMethod() { + return "$derivative"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 4052b2cbaa..928869e93b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -91,6 +91,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("subtract", arrayArgRef().forOperator("$subtract")); map.put("trunc", singleArgRef().forOperator("$trunc")); map.put("round", arrayArgRef().forOperator("$round")); + map.put("derivative", mapArgRef().forOperator("$derivative").mappingParametersTo("input", "unit")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 940a315239..b4f3cdadb6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -59,4 +59,11 @@ void roundShouldWithPlaceFromExpression() { .toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(new Document("$round", Arrays.asList("$field", new Document("$first", "$source")))); } + + @Test // GH-3716 + void rendersDerivativeCorrectly() { + + assertThat(valueOf("miles").derivative("hour").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }")); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index ee55818018..2653c52f2d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -989,6 +989,11 @@ void rendersShiftWithDefault() { } @Nullable + @Test // GH-3716 + void shouldRenderDerivative() { + assertThat(transform("derivative(miles, 'hour')")).isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From 10c0203605b421d47764866303113b02dfdc4e3e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 14:29:46 +0200 Subject: [PATCH 0496/1381] Polishing. Accept window units in addition to plain strings. Document operator. See: #3716 Original pull request: #3742. --- .../core/aggregation/ArithmeticOperators.java | 21 ++++++++++++++++++- .../ArithmeticOperatorsUnitTests.java | 6 ++++-- .../reference/aggregation-framework.adoc | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index fe54f2434e..39579fc7b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -17,6 +17,7 @@ import java.util.Collections; import java.util.List; +import java.util.Locale; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Avg; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.CovariancePop; @@ -26,6 +27,8 @@ import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevPop; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.StdDevSamp; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Sum; +import org.springframework.data.mongodb.core.aggregation.SetWindowFieldsOperation.WindowUnit; +import org.springframework.data.mongodb.core.aggregation.SetWindowFieldsOperation.WindowUnits; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -34,6 +37,7 @@ * Gateway to {@literal Arithmetic} aggregation operations that perform math operations on numbers. * * @author Christoph Strobl + * @author Mark Paluch * @since 1.10 */ public class ArithmeticOperators { @@ -600,7 +604,22 @@ public Round roundToPlace(int place) { * @since 3.3 */ public Derivative derivative() { - return derivative(null); + return derivative((String) null); + } + + /** + * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. + * + * @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR}, + * {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply. + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Derivative derivative(WindowUnit unit) { + + Assert.notNull(unit, "Window unit must not be null"); + + return derivative(unit.name().toLowerCase(Locale.ROOT)); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index b4f3cdadb6..da03bc5c61 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -28,8 +28,9 @@ * Unit tests for {@link Round}. * * @author Christoph Strobl + * @author Mark Paluch */ -public class ArithmeticOperatorsUnitTests { +class ArithmeticOperatorsUnitTests { @Test // DATAMONGO-2370 void roundShouldWithoutPlace() { @@ -63,7 +64,8 @@ void roundShouldWithPlaceFromExpression() { @Test // GH-3716 void rendersDerivativeCorrectly() { - assertThat(valueOf("miles").derivative("hour").toDocument(Aggregation.DEFAULT_CONTEXT)) + assertThat( + valueOf("miles").derivative(SetWindowFieldsOperation.WindowUnits.HOUR).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }")); } } diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index 547b3b1530..2624e6c27e 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -85,7 +85,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (+++*+++ via `plus`), `ceil`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc` +| `abs`, `add` (+++*+++ via `plus`), `ceil`, `derivative`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` @@ -119,6 +119,7 @@ At the time of this writing, we provide support for the following Aggregation Op | Script Aggregation Operators | `function`, `accumulator` + |=== +++*+++ The operation is mapped or added by Spring Data MongoDB. From 6bd0f758fed10eb92c55bd22da7f5b8b40b387a1 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 23 Jul 2021 10:10:18 +0200 Subject: [PATCH 0497/1381] Extend support for `$ifNull` to cover multiple conditions. Closes: #3720 Original pull request: #3745. --- .../aggregation/ConditionalOperators.java | 69 +++++++++++++++---- .../ConditionalOperatorsUnitTests.java | 35 ++++++++++ 2 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java index 1d3890ce89..95a0290ec2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -282,19 +283,29 @@ public Document toDocument(AggregationOperationContext context) { List list = new ArrayList(); - if (condition instanceof Field) { - list.add(context.getReference((Field) condition).toString()); - } else if (condition instanceof AggregationExpression) { - list.add(((AggregationExpression) condition).toDocument(context)); + if(condition instanceof Collection) { + for(Object val : ((Collection)this.condition)) { + list.add(mapCondition(val, context)); + } } else { - list.add(condition); + list.add(mapCondition(condition, context)); } list.add(resolve(value, context)); - return new Document("$ifNull", list); } + private Object mapCondition(Object condition, AggregationOperationContext context) { + + if (condition instanceof Field) { + return context.getReference((Field) condition).toString(); + } else if (condition instanceof AggregationExpression) { + return ((AggregationExpression) condition).toDocument(context); + } else { + return condition; + } + } + private Object resolve(Object value, AggregationOperationContext context) { if (value instanceof Field) { @@ -323,15 +334,34 @@ public interface IfNullBuilder { /** * @param expression the expression to check for a {@literal null} value, field name must not be {@literal null} * or empty. - * @return the {@link ThenBuilder} + * @return the {@link ThenBuilder}. */ ThenBuilder ifNull(AggregationExpression expression); } + /** + * @author Christoph Strobl + * @since 3.3 + */ + public interface OrBuilder { + + /** + * @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null}. + * @return the {@link ThenBuilder} + */ + ThenBuilder orIfNull(String fieldReference); + + /** + * @param expression the expression to check for a {@literal null} value, + * @return the {@link ThenBuilder}. + */ + ThenBuilder orIfNull(AggregationExpression expression); + } + /** * @author Mark Paluch */ - public interface ThenBuilder { + public interface ThenBuilder extends OrBuilder { /** * @param value the value to be used if the {@code $ifNull} condition evaluates {@literal true}. Can be a @@ -361,9 +391,10 @@ public interface ThenBuilder { */ static final class IfNullOperatorBuilder implements IfNullBuilder, ThenBuilder { - private @Nullable Object condition; + private @Nullable List conditions; private IfNullOperatorBuilder() { + conditions = new ArrayList<>(); } /** @@ -381,7 +412,7 @@ public static IfNullOperatorBuilder newBuilder() { public ThenBuilder ifNull(String fieldReference) { Assert.hasText(fieldReference, "FieldReference name must not be null or empty!"); - this.condition = Fields.field(fieldReference); + this.conditions.add(Fields.field(fieldReference)); return this; } @@ -392,15 +423,25 @@ public ThenBuilder ifNull(String fieldReference) { public ThenBuilder ifNull(AggregationExpression expression) { Assert.notNull(expression, "AggregationExpression name must not be null or empty!"); - this.condition = expression; + this.conditions.add(expression); return this; } + @Override + public ThenBuilder orIfNull(String fieldReference) { + return ifNull(fieldReference); + } + + @Override + public ThenBuilder orIfNull(AggregationExpression expression) { + return ifNull(expression); + } + /* (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.ConditionalOperators.IfNull.ThenBuilder#then(java.lang.Object) */ public IfNull then(Object value) { - return new IfNull(condition, value); + return new IfNull(conditions, value); } /* (non-Javadoc) @@ -409,7 +450,7 @@ public IfNull then(Object value) { public IfNull thenValueOf(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); - return new IfNull(condition, Fields.field(fieldReference)); + return new IfNull(conditions, Fields.field(fieldReference)); } /* (non-Javadoc) @@ -418,7 +459,7 @@ public IfNull thenValueOf(String fieldReference) { public IfNull thenValueOf(AggregationExpression expression) { Assert.notNull(expression, "Expression must not be null!"); - return new IfNull(condition, expression); + return new IfNull(conditions, expression); } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java new file mode 100644 index 0000000000..132600cbb5 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.*; + +import org.bson.Document; +import org.junit.jupiter.api.Test; + +/** + * @author Christoph Strobl + */ +public class ConditionalOperatorsUnitTests { + + @Test // GH-3720 + void rendersIfNullWithMultipleConditionalValuesCorrectly() { + + assertThat(ifNull("description").orIfNull("quantity").then("Unspecified").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $ifNull: [ \"$description\", \"$quantity\", \"Unspecified\" ] }")); + } +} From fd0a402c99e402c6ef69538f34be515c12dc54d6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 14:34:05 +0200 Subject: [PATCH 0498/1381] Polishing. See #3720 Original pull request: #3745. --- .../aggregation/ConditionalOperators.java | 37 ++++++++++--------- .../ConditionalOperatorsUnitTests.java | 4 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java index 95a0290ec2..1979ec78f4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperators.java @@ -236,7 +236,7 @@ private boolean usesCriteriaDefinition() { * * @author Mark Paluch * @see https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/">https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/ */ public static class IfNull implements AggregationExpression { @@ -252,7 +252,8 @@ private IfNull(Object condition, Object value) { /** * Creates new {@link IfNull}. * - * @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null}. + * @param fieldReference the field to check for a {@literal null} value, field reference must not be + * {@literal null}. * @return never {@literal null}. */ public static ThenBuilder ifNull(String fieldReference) { @@ -265,7 +266,7 @@ public static ThenBuilder ifNull(String fieldReference) { * Creates new {@link IfNull}. * * @param expression the expression to check for a {@literal null} value, field reference must not be - * {@literal null}. + * {@literal null}. * @return never {@literal null}. */ public static ThenBuilder ifNull(AggregationExpression expression) { @@ -283,8 +284,8 @@ public Document toDocument(AggregationOperationContext context) { List list = new ArrayList(); - if(condition instanceof Collection) { - for(Object val : ((Collection)this.condition)) { + if (condition instanceof Collection) { + for (Object val : ((Collection) this.condition)) { list.add(mapCondition(val, context)); } } else { @@ -326,14 +327,14 @@ public interface IfNullBuilder { /** * @param fieldReference the field to check for a {@literal null} value, field reference must not be - * {@literal null}. + * {@literal null}. * @return the {@link ThenBuilder} */ ThenBuilder ifNull(String fieldReference); /** * @param expression the expression to check for a {@literal null} value, field name must not be {@literal null} - * or empty. + * or empty. * @return the {@link ThenBuilder}. */ ThenBuilder ifNull(AggregationExpression expression); @@ -346,7 +347,8 @@ public interface IfNullBuilder { public interface OrBuilder { /** - * @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null}. + * @param fieldReference the field to check for a {@literal null} value, field reference must not be + * {@literal null}. * @return the {@link ThenBuilder} */ ThenBuilder orIfNull(String fieldReference); @@ -365,8 +367,8 @@ public interface ThenBuilder extends OrBuilder { /** * @param value the value to be used if the {@code $ifNull} condition evaluates {@literal true}. Can be a - * {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB - * representation but must not be {@literal null}. + * {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB + * representation but must not be {@literal null}. * @return new instance of {@link IfNull}. */ IfNull then(Object value); @@ -499,7 +501,7 @@ public static Switch switchCases(CaseOperator... conditions) { public static Switch switchCases(List conditions) { Assert.notNull(conditions, "Conditions must not be null!"); - return new Switch(Collections.singletonMap("branches", new ArrayList(conditions))); + return new Switch(Collections. singletonMap("branches", new ArrayList(conditions))); } /** @@ -586,7 +588,7 @@ public interface ThenBuilder { * @author Mark Paluch * @author Christoph Strobl * @see https://docs.mongodb.com/manual/reference/operator/aggregation/cond/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/cond/">https://docs.mongodb.com/manual/reference/operator/aggregation/cond/ */ public static class Cond implements AggregationExpression { @@ -847,8 +849,8 @@ public interface ThenBuilder { /** * @param value the value to be used if the condition evaluates {@literal true}. Can be a {@link Document}, a - * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but - * must not be {@literal null}. + * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but + * must not be {@literal null}. * @return the {@link OtherwiseBuilder} */ OtherwiseBuilder then(Object value); @@ -873,8 +875,8 @@ public interface OtherwiseBuilder { /** * @param value the value to be used if the condition evaluates {@literal false}. Can be a {@link Document}, a - * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but - * must not be {@literal null}. + * value that is supported by MongoDB or a value that can be converted to a MongoDB representation but + * must not be {@literal null}. * @return the {@link Cond} */ Cond otherwise(Object value); @@ -902,8 +904,7 @@ static class ConditionalExpressionBuilder implements WhenBuilder, ThenBuilder, O private @Nullable Object condition; private @Nullable Object thenValue; - private ConditionalExpressionBuilder() { - } + private ConditionalExpressionBuilder() {} /** * Creates a new builder for {@link Cond}. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java index 132600cbb5..3b88781616 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConditionalOperatorsUnitTests.java @@ -22,9 +22,11 @@ import org.junit.jupiter.api.Test; /** + * Unit tests for {@link ConditionalOperators}. + * * @author Christoph Strobl */ -public class ConditionalOperatorsUnitTests { +class ConditionalOperatorsUnitTests { @Test // GH-3720 void rendersIfNullWithMultipleConditionalValuesCorrectly() { From df2b2a2f685b46939126c5aa9998d34a8e5270d6 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 23 Jul 2021 10:46:27 +0200 Subject: [PATCH 0499/1381] Add support for `$integral` aggregation operator. Closes: #3721 Original pull request: #3746. --- .../core/aggregation/ArithmeticOperators.java | 87 +++++++++++++++++-- .../core/spel/MethodReferenceNode.java | 1 + .../ArithmeticOperatorsUnitTests.java | 10 +++ .../SpelExpressionTransformerUnitTests.java | 10 +++ 4 files changed, 100 insertions(+), 8 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 39579fc7b6..4d86bac98e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -216,6 +216,27 @@ public Floor floor() { return usesFieldRef() ? Floor.floorValueOf(fieldReference) : Floor.floorValueOf(expression); } + /** + * Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value. + * + * @return new instance of {@link Integral}. + * @since 3.3 + */ + public Integral integral() { + return usesFieldRef() ? Integral.integralOf(fieldReference) : Integral.integralOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value. + * + * @param unit the unit of measure. + * @return new instance of {@link Integral}. + * @since 3.3 + */ + public Integral integral(String unit) { + return integral().unit(unit); + } + /** * Creates new {@link AggregationExpression} that calculates the natural logarithm ln (i.e loge) of the assoicated * number. @@ -520,8 +541,8 @@ public StdDevSamp stdDevSamp() { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given - * field to calculate the population covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the + * given field to calculate the population covariance of the two. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -532,8 +553,8 @@ public CovariancePop covariancePop(String fieldReference) { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given - * {@link AggregationExpression expression} to calculate the population covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the + * given {@link AggregationExpression expression} to calculate the population covariance of the two. * * @param expression must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -548,8 +569,8 @@ private CovariancePop covariancePop() { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the given - * field to calculate the sample covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the value of the + * given field to calculate the sample covariance of the two. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -560,8 +581,8 @@ public CovarianceSamp covarianceSamp(String fieldReference) { } /** - * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the given - * {@link AggregationExpression expression} to calculate the sample covariance of the two. + * Creates new {@link AggregationExpression} that uses the previous input (field/expression) and the result of the + * given {@link AggregationExpression expression} to calculate the sample covariance of the two. * * @param expression must not be {@literal null}. * @return new instance of {@link CovariancePop}. @@ -1798,4 +1819,54 @@ protected String getMongoMethod() { return "$derivative"; } } + + /** + * Value object to represent an {@link AggregationExpression expression} that calculates the approximation for the + * mathematical integral value. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Integral extends AbstractAggregationExpression { + + private Integral(Object value) { + super(value); + } + + /** + * Create a new instance of {@link Integral} for the value stored at the given field holding a numeric value. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Integral}. + */ + public static Integral integralOf(String fieldReference) { + return new Integral(Collections.singletonMap("input", Fields.field(fieldReference))); + } + + /** + * Create a new instance of {@link Integral} for the value provided by the given expression that resolves to a + * numeric value. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Integral}. + */ + public static Integral integralOf(AggregationExpression expression) { + return new Integral(Collections.singletonMap("input", expression)); + } + + /** + * Set the unit of measure. + * + * @param unit the unit of measure. + * @return new instance of {@link Integral}. + */ + public Integral unit(String unit) { + return new Integral(append("unit", unit)); + } + + @Override + protected String getMongoMethod() { + return "$integral"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 928869e93b..9be1368caf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -92,6 +92,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("trunc", singleArgRef().forOperator("$trunc")); map.put("round", arrayArgRef().forOperator("$round")); map.put("derivative", mapArgRef().forOperator("$derivative").mappingParametersTo("input", "unit")); + map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index da03bc5c61..1aab826a23 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -68,4 +68,14 @@ void rendersDerivativeCorrectly() { valueOf("miles").derivative(SetWindowFieldsOperation.WindowUnits.HOUR).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }")); } + + @Test // GH-3721 + void rendersIntegral() { + assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\" } }")); + } + + @Test // GH-3721 + void rendersIntegralWithUnit() { + assertThat(valueOf("kilowatts").integral("hour").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }")); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 2653c52f2d..a0fad05a3c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -994,6 +994,16 @@ void shouldRenderDerivative() { assertThat(transform("derivative(miles, 'hour')")).isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }")); } + @Test // GH-3721 + public void shouldRenderIntegral() { + assertThat(transform("integral(field)")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\" }}")); + } + + @Test // GH-3721 + public void shouldIntegralWithUnit() { + assertThat(transform("integral(field, 'hour')")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From 2a3a4cf030eefdcdd491cd68c532cfffff86bd20 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 14:59:58 +0200 Subject: [PATCH 0500/1381] Polishing. Fix method order from earlier merges. Add missing Javadoc. Simplify tests. Update documentation. See #3721 Original pull request: #3746. --- .../core/aggregation/ArithmeticOperators.java | 118 ++++++++++++------ .../ArithmeticOperatorsUnitTests.java | 11 +- .../SpelExpressionTransformerUnitTests.java | 51 ++++---- .../reference/aggregation-framework.adoc | 2 +- 4 files changed, 109 insertions(+), 73 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 4d86bac98e..159c6bbeae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -155,6 +155,46 @@ public Ceil ceil() { return usesFieldRef() ? Ceil.ceilValueOf(fieldReference) : Ceil.ceilValueOf(expression); } + /** + * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. + * + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Derivative derivative() { + return derivative((String) null); + } + + /** + * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. + * + * @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR}, + * {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply. + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Derivative derivative(WindowUnit unit) { + + Assert.notNull(unit, "Window unit must not be null"); + + return derivative(unit.name().toLowerCase(Locale.ROOT)); + } + + /** + * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. + * + * @param unit The time unit ({@literal week, day, hour, minute, second, millisecond}) to apply can be + * {@literal null}. + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Derivative derivative(@Nullable String unit) { + + Derivative derivative = usesFieldRef() ? Derivative.derivativeOf(fieldReference) + : Derivative.derivativeOf(expression); + return StringUtils.hasText(unit) ? derivative.unit(unit) : derivative; + } + /** * Creates new {@link AggregationExpression} that ivides the associated number by number referenced via * {@literal fieldReference}. @@ -226,6 +266,21 @@ public Integral integral() { return usesFieldRef() ? Integral.integralOf(fieldReference) : Integral.integralOf(expression); } + /** + * Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value. + * + * @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR}, + * {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply. + * @return new instance of {@link Derivative}. + * @since 3.3 + */ + public Integral integral(WindowUnit unit) { + + Assert.notNull(unit, "Window unit must not be null"); + + return integral(unit.name().toLowerCase(Locale.ROOT)); + } + /** * Creates new {@link AggregationExpression} that calculates the approximation for the mathematical integral value. * @@ -234,6 +289,9 @@ public Integral integral() { * @since 3.3 */ public Integral integral(String unit) { + + Assert.hasText(unit, "Unit must not be empty!"); + return integral().unit(unit); } @@ -618,46 +676,6 @@ public Round roundToPlace(int place) { return round().place(place); } - /** - * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. - * - * @return new instance of {@link Derivative}. - * @since 3.3 - */ - public Derivative derivative() { - return derivative((String) null); - } - - /** - * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. - * - * @param unit The time unit ({@link WindowUnits#WEEK}, {@link WindowUnits#DAY}, {@link WindowUnits#HOUR}, - * {@link WindowUnits#MINUTE}, {@link WindowUnits#SECOND}, {@link WindowUnits#MILLISECOND}) to apply. - * @return new instance of {@link Derivative}. - * @since 3.3 - */ - public Derivative derivative(WindowUnit unit) { - - Assert.notNull(unit, "Window unit must not be null"); - - return derivative(unit.name().toLowerCase(Locale.ROOT)); - } - - /** - * Creates new {@link AggregationExpression} that calculates the mathematical derivative value. - * - * @param unit The time unit ({@literal week, day, hour, minute, second, millisecond}) to apply can be - * {@literal null}. - * @return new instance of {@link Derivative}. - * @since 3.3 - */ - public Derivative derivative(@Nullable String unit) { - - Derivative derivative = usesFieldRef() ? Derivative.derivativeOf(fieldReference) - : Derivative.derivativeOf(expression); - return StringUtils.hasText(unit) ? derivative.unit(unit) : derivative; - } - private boolean usesFieldRef() { return fieldReference != null; } @@ -1792,16 +1810,36 @@ protected String getMongoMethod() { } } + /** + * Value object to represent an {@link AggregationExpression expression} that calculates the average rate of change + * within the specified window. + * + * @author Christoph Strobl + * @since 3.3 + */ public static class Derivative extends AbstractAggregationExpression { private Derivative(Object value) { super(value); } + /** + * Create a new instance of {@link Derivative} for the value stored at the given field holding a numeric value. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Derivative}. + */ public static Derivative derivativeOf(String fieldReference) { return new Derivative(Collections.singletonMap("input", Fields.field(fieldReference))); } + /** + * Create a new instance of {@link Derivative} for the value provided by the given expression that resolves to a + * numeric value. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Derivative}. + */ public static Derivative derivativeOf(AggregationExpression expression) { return new Derivative(Collections.singletonMap("input", expression)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 1aab826a23..d57363d91c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -15,8 +15,8 @@ */ package org.springframework.data.mongodb.core.aggregation; -import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.aggregation.ArithmeticOperators.*; +import static org.springframework.data.mongodb.test.util.Assertions.*; import java.util.Arrays; import java.util.Collections; @@ -66,16 +66,19 @@ void rendersDerivativeCorrectly() { assertThat( valueOf("miles").derivative(SetWindowFieldsOperation.WindowUnits.HOUR).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $derivative: { input: \"$miles\", unit: \"hour\" } }")); + .isEqualTo("{ $derivative: { input: \"$miles\", unit: \"hour\" } }"); } @Test // GH-3721 void rendersIntegral() { - assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\" } }")); + assertThat(valueOf("kilowatts").integral().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $integral : { input : \"$kilowatts\" } }"); } @Test // GH-3721 void rendersIntegralWithUnit() { - assertThat(valueOf("kilowatts").integral("hour").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }")); + assertThat(valueOf("kilowatts").integral(SetWindowFieldsOperation.WindowUnits.HOUR) + .toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }"); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index a0fad05a3c..0450e556c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -23,8 +23,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; + import org.springframework.data.mongodb.core.Person; -import org.springframework.lang.Nullable; /** * Unit tests for {@link SpelExpressionTransformer}. @@ -152,8 +152,8 @@ void shouldRenderBinaryExpressionWithMixedSignsCorrectly() { @Test // DATAMONGO-774 void shouldRenderConsecutiveOperationsInComplexExpression() { - assertThat(transform("1 + 1 + (1 + 1 + 1) / q")).isEqualTo( - Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}")); + assertThat(transform("1 + 1 + (1 + 1 + 1) / q")) + .isEqualTo(Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}")); } @Test // DATAMONGO-774 @@ -189,8 +189,7 @@ void shouldRenderCompoundExpressionsWithIndexerAndFieldReference() { Person person = new Person(); person.setAge(10); - assertThat(transform("[0].age + a.c", person)) - .isEqualTo(Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }")); + assertThat(transform("[0].age + a.c", person)).isEqualTo(Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }")); } @Test // DATAMONGO-840 @@ -216,8 +215,7 @@ void shouldRenderMethodReferenceNodeNot() { @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSetEquals() { - assertThat(transform("setEquals(a, b)")) - .isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("setEquals(a, b)")).isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 @@ -379,8 +377,7 @@ void shouldRenderMethodReferenceTrunc() { @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeConcat() { - assertThat(transform("concat(a, b, 'c')")) - .isEqualTo(Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}")); + assertThat(transform("concat(a, b, 'c')")).isEqualTo(Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}")); } @Test // DATAMONGO-1530 @@ -400,8 +397,7 @@ void shouldRenderMethodReferenceToUpper() { @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeStrCaseCmp() { - assertThat(transform("strcasecmp(a, b)")) - .isEqualTo(Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("strcasecmp(a, b)")).isEqualTo(Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}")); } @Test // DATAMONGO-1530 @@ -411,8 +407,7 @@ void shouldRenderMethodReferenceMeta() { @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeArrayElemAt() { - assertThat(transform("arrayElemAt(a, 10)")) - .isEqualTo(Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}")); + assertThat(transform("arrayElemAt(a, 10)")).isEqualTo(Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}")); } @Test // DATAMONGO-1530 @@ -511,15 +506,14 @@ void shouldRenderMethodReferenceMillisecond() { @Test // DATAMONGO-1530 void shouldRenderMethodReferenceDateToString() { - assertThat(transform("dateToString('%Y-%m-%d', $date)")).isEqualTo( - Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}")); + assertThat(transform("dateToString('%Y-%m-%d', $date)")) + .isEqualTo(Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}")); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceCond() { assertThat(transform("cond(qty > 250, 30, 20)")).isEqualTo( - Document - .parse("{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}")); + Document.parse("{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}")); } @Test // DATAMONGO-1530 @@ -633,8 +627,7 @@ void shouldRenderOperationNodeAnd() { @Test // DATAMONGO-1530 void shouldRenderComplexOperationNodeAnd() { assertThat(transform("1+2 && concat(a, b) && true")).isEqualTo( - Document - .parse("{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); + Document.parse("{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); } @Test // DATAMONGO-1530 @@ -644,8 +637,7 @@ void shouldRenderNotCorrectly() { @Test // DATAMONGO-1530 void shouldRenderComplexNotCorrectly() { - assertThat(transform("!(foo > 10)")) - .isEqualTo(Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}")); + assertThat(transform("!(foo > 10)")).isEqualTo(Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}")); } @Test // DATAMONGO-1548 @@ -951,12 +943,14 @@ void shouldRenderRoundWithPlace() { @Test // GH-3712 void shouldRenderCovariancePop() { - assertThat(transform("covariancePop(field1, field2)")).isEqualTo(Document.parse("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}")); + assertThat(transform("covariancePop(field1, field2)")) + .isEqualTo(Document.parse("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}")); } @Test // GH-3712 void shouldRenderCovarianceSamp() { - assertThat(transform("covarianceSamp(field1, field2)")).isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}")); + assertThat(transform("covarianceSamp(field1, field2)")) + .isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}")); } @Test // GH-3715 @@ -988,20 +982,21 @@ void rendersShiftWithDefault() { .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }")); } - @Nullable @Test // GH-3716 void shouldRenderDerivative() { - assertThat(transform("derivative(miles, 'hour')")).isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }")); + assertThat(transform("derivative(miles, 'hour')")) + .isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }")); } @Test // GH-3721 - public void shouldRenderIntegral() { + void shouldRenderIntegral() { assertThat(transform("integral(field)")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\" }}")); } @Test // GH-3721 - public void shouldIntegralWithUnit() { - assertThat(transform("integral(field, 'hour')")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}")); + void shouldRenderIntegralWithUnit() { + assertThat(transform("integral(field, 'hour')")) + .isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}")); } private Object transform(String expression, Object... params) { diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index 2624e6c27e..9b00811a7b 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -85,7 +85,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (+++*+++ via `plus`), `ceil`, `derivative`, `divide`, `exp`, `floor`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc` +| `abs`, `add` (+++*+++ via `plus`), `ceil`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` From ec16b873b7f52477812c92b7504ec8a5306ede2c Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 28 Jul 2021 08:03:38 +0200 Subject: [PATCH 0501/1381] Add support for `$degreesToRadians` aggregation operator. Closes: #3714 Original pull request: #3755. --- .../core/aggregation/ConvertOperators.java | 58 +++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 1 + .../ConvertOperatorsUnitTests.java | 7 +++ .../SpelExpressionTransformerUnitTests.java | 5 ++ 4 files changed, 71 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java index 315a463e1f..b34933444a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java @@ -231,6 +231,16 @@ public ToString convertToString() { return ToString.toString(valueObject()); } + /** + * {@link AggregationExpression} for {@code $degreesToRadians} that converts an input value measured in degrees to radians.\ + * + * @return new instance of {@link DegreesToRadians}. + * @since 3.3 + */ + public DegreesToRadians convertDegreesToRadians() { + return DegreesToRadians.degreesToRadians(valueObject()); + } + private Convert createConvert() { return usesFieldRef() ? Convert.convertValueOf(fieldReference) : Convert.convertValueOf(expression); } @@ -692,4 +702,52 @@ protected String getMongoMethod() { return "$toString"; } } + + /** + * {@link AggregationExpression} for {@code $degreesToRadians} that converts an input value measured in degrees to radians. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class DegreesToRadians extends AbstractAggregationExpression { + + private DegreesToRadians(Object value) { + super(value); + } + + /** + * Create a new instance of {@link DegreesToRadians} that converts the value of the given field, measured in degrees, to radians. + * + * @param fieldName must not be {@literal null}. + * @return new instance of {@link DegreesToRadians}. + */ + public static DegreesToRadians degreesToRadiansOf(String fieldName) { + return degreesToRadians(Fields.field(fieldName)); + } + + /** + * Create a new instance of {@link DegreesToRadians} that converts the result of the given {@link AggregationExpression expression}, measured in degrees, to radians. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link DegreesToRadians}. + */ + public static DegreesToRadians degreesToRadiansOf(AggregationExpression expression) { + return degreesToRadians(expression); + } + + /** + * Create a new instance of {@link DegreesToRadians} that converts the given value, measured in degrees, to radians. + * + * @param value must not be {@literal null}. + * @return new instance of {@link DegreesToRadians}. + */ + public static DegreesToRadians degreesToRadians(Object value) { + return new DegreesToRadians(value); + } + + @Override + protected String getMongoMethod() { + return "$degreesToRadians"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 9be1368caf..f0799a1af6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -199,6 +199,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("toLong", singleArgRef().forOperator("$toLong")); map.put("toObjectId", singleArgRef().forOperator("$toObjectId")); map.put("toString", singleArgRef().forOperator("$toString")); + map.put("degreesToRadians", singleArgRef().forOperator("$degreesToRadians")); FUNCTIONS = Collections.unmodifiableMap(map); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java index a44c932723..c794cf8102 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ConvertOperatorsUnitTests.java @@ -222,4 +222,11 @@ public void toStringUsingExpression() { assertThat(ConvertOperators.valueOf(EXPRESSION).convertToString().toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(Document.parse("{ $toString: " + EXPRESSION_STRING + " } ")); } + + @Test // GH-3714 + void degreesToRadiansUsingFieldReference() { + + assertThat(ConvertOperators.valueOf("angle_a").convertDegreesToRadians().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $degreesToRadians : \"$angle_a\"}")); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 0450e556c4..9cad6cbb15 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -941,6 +941,11 @@ void shouldRenderRoundWithPlace() { assertThat(transform("round(field, 2)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\", 2]}")); } + @Test // GH-3714 + void shouldRenderDegreesToRadians() { + assertThat(transform("degreesToRadians(angle_a)")).isEqualTo(Document.parse("{ \"$degreesToRadians\" : \"$angle_a\"}")); + } + @Test // GH-3712 void shouldRenderCovariancePop() { assertThat(transform("covariancePop(field1, field2)")) From 0db47169cffca0ca3af462c6f61d9178538cfad9 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 28 Jul 2021 09:40:52 +0200 Subject: [PATCH 0502/1381] Add support for `$sin` and `$sinh` aggregation operators. Closes: #3728 Original pull request: #3755. --- .../core/aggregation/ArithmeticOperators.java | 246 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 2 + .../ArithmeticOperatorsUnitTests.java | 28 ++ .../SpelExpressionTransformerUnitTests.java | 10 + 4 files changed, 286 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 159c6bbeae..db328338e3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -31,6 +31,7 @@ import org.springframework.data.mongodb.core.aggregation.SetWindowFieldsOperation.WindowUnits; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -676,6 +677,48 @@ public Round roundToPlace(int place) { return round().place(place); } + /** + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in {@link AngularDimension#RADIANS radians}. + * + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Sin sin() { + return sin(AngularDimension.RADIANS); + } + + /** + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value in the given {@link AngularDimension unit}. + * + * @param unit the unit of measure. + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Sin sin(AngularDimension unit) { + return usesFieldRef() ? Sin.sinOf(fieldReference, unit) : Sin.sinOf(expression, unit); + } + + /** + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in {@link AngularDimension#RADIANS radians}. + * + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Sinh sinh() { + return sinh(AngularDimension.RADIANS); + } + + /** + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value. + * + * @param unit the unit of measure. + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Sinh sinh(AngularDimension unit) { + return usesFieldRef() ? Sinh.sinhOf(fieldReference, unit) : Sinh.sinhOf(expression, unit); + } + private boolean usesFieldRef() { return fieldReference != null; } @@ -1907,4 +1950,207 @@ protected String getMongoMethod() { return "$integral"; } } + + /** + * The unit of measure for computations that operate upon angles. + * + * @author Christoph Strobl + * @since 3.3 + */ + public enum AngularDimension { + RADIANS, DEGREES + } + + /** + * An {@link AggregationExpression expression} that calculates the sine of a value that is measured in radians. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Sin extends AbstractAggregationExpression { + + private Sin(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in + * {@link AngularDimension#RADIANS radians}. + *

      + * Use {@code sinhOf("angle", DEGREES)} as shortcut for

      { $sinh : { $degreesToRadians : "$angle" } }
      . + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link Sin}. + */ + public static Sin sinOf(String fieldReference) { + return sinOf(fieldReference, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Sin}. + */ + public static Sin sinOf(String fieldReference, AngularDimension unit) { + return sin(Fields.field(fieldReference), unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link Sin}. + */ + public static Sin sinOf(AggregationExpression expression) { + return sinOf(expression, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Sin}. + */ + public static Sin sinOf(AggregationExpression expression, AngularDimension unit) { + return sin(expression, unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value + * @return new instance of {@link Sin}. + */ + public static Sin sin(Object value) { + return sin(value, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Sin}. + */ + public static Sin sin(Object value, AngularDimension unit) { + + if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + return new Sin(ConvertOperators.DegreesToRadians.degreesToRadians(value)); + } + return new Sin(value); + } + + @Override + protected String getMongoMethod() { + return "$sin"; + } + } + + /** + * An {@link AggregationExpression expression} that calculates the hyperbolic sine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Sinh extends AbstractAggregationExpression { + + private Sinh(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link Sin}. + */ + public static Sinh sinhOf(String fieldReference) { + return sinhOf(fieldReference, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in + * the given {@link AngularDimension unit}. + *

      + * Use {@code sinhOf("angle", DEGREES)} as shortcut for

      { $sinh : { $degreesToRadians : "$angle" } }
      . + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Sin}. + */ + public static Sinh sinhOf(String fieldReference, AngularDimension unit) { + return sinh(Fields.field(fieldReference), unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in + * {@link AngularDimension#RADIANS}. + *

      + * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link Sin}. + */ + public static Sinh sinhOf(AggregationExpression expression) { + return sinhOf(expression, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in + * the given {@link AngularDimension unit}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Sin}. + */ + public static Sinh sinhOf(AggregationExpression expression, AngularDimension unit) { + return sinh(expression, unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link Sin}. + */ + public static Sinh sinh(Object value) { + return sinh(value, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in + * the given {@link AngularDimension unit}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Sin}. + */ + public static Sinh sinh(Object value, AngularDimension unit) { + + if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + return new Sinh(ConvertOperators.DegreesToRadians.degreesToRadians(value)); + } + return new Sinh(value); + } + + @Override + protected String getMongoMethod() { + return "$sinh"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index f0799a1af6..9ee12be1eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -93,6 +93,8 @@ public class MethodReferenceNode extends ExpressionNode { map.put("round", arrayArgRef().forOperator("$round")); map.put("derivative", mapArgRef().forOperator("$derivative").mappingParametersTo("input", "unit")); map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit")); + map.put("sin", singleArgRef().forOperator("$sin")); + map.put("sinh", singleArgRef().forOperator("$sinh")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index d57363d91c..cc32a94323 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -81,4 +81,32 @@ void rendersIntegralWithUnit() { .toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }"); } + + @Test // GH-3728 + void rendersSin() { + + assertThat(valueOf("angle").sin().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $sin : \"$angle\" }")); + } + + @Test // GH-3728 + void rendersSinWithValueInDegrees() { + + assertThat(valueOf("angle").sin(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $sin : { $degreesToRadians : \"$angle\" } }")); + } + + @Test // GH-3728 + void rendersSinh() { + + assertThat(valueOf("angle").sinh().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $sinh : \"$angle\" }")); + } + + @Test // GH-3728 + void rendersSinhWithValueInDegrees() { + + assertThat(valueOf("angle").sinh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $sinh : { $degreesToRadians : \"$angle\" } }")); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 9cad6cbb15..e250241558 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1004,6 +1004,16 @@ void shouldRenderIntegralWithUnit() { .isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}")); } + @Test // GH-3728 + void shouldRenderSin() { + assertThat(transform("sin(angle)")).isEqualTo(Document.parse("{ \"$sin\" : \"$angle\"}")); + } + + @Test // GH-3728 + void shouldRenderSinh() { + assertThat(transform("sinh(angle)")).isEqualTo(Document.parse("{ \"$sinh\" : \"$angle\"}")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From 73d5886aae13082d24b7f49db91da322da509952 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 28 Jul 2021 09:54:05 +0200 Subject: [PATCH 0503/1381] Add support for `$tan` and `$tanh` aggregation operators. Closes: #3730 Original pull request: #3755. --- .../core/aggregation/ArithmeticOperators.java | 251 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 2 + .../ArithmeticOperatorsUnitTests.java | 29 ++ .../SpelExpressionTransformerUnitTests.java | 10 + 4 files changed, 292 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index db328338e3..e26e41f651 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -719,6 +719,51 @@ public Sinh sinh(AngularDimension unit) { return usesFieldRef() ? Sinh.sinhOf(fieldReference, unit) : Sinh.sinhOf(expression, unit); } + /** + * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value given in + * {@link AngularDimension#RADIANS radians}. + * + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Tan tan() { + return tan(AngularDimension.RADIANS); + } + + /** + * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value in the given + * {@link AngularDimension unit}. + * + * @param unit the unit of measure. + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Tan tan(AngularDimension unit) { + return usesFieldRef() ? Tan.tanOf(fieldReference, unit) : Tan.tanOf(expression, unit); + } + + /** + * Creates new {@link AggregationExpression} that calculates the hyperbolic tangent of a numeric value given in + * {@link AngularDimension#RADIANS radians}. + * + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Tanh tanh() { + return tanh(AngularDimension.RADIANS); + } + + /** + * Creates new {@link AggregationExpression} that calculates the hyperbolic tangent of a numeric value. + * + * @param unit the unit of measure. + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Tanh tanh(AngularDimension unit) { + return usesFieldRef() ? Tanh.tanhOf(fieldReference, unit) : Tanh.tanhOf(expression, unit); + } + private boolean usesFieldRef() { return fieldReference != null; } @@ -2153,4 +2198,210 @@ protected String getMongoMethod() { return "$sinh"; } } + + /** + * An {@link AggregationExpression expression} that calculates the tangent of a value that is measured in radians. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Tan extends AbstractAggregationExpression { + + private Tan(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in + * {@link AngularDimension#RADIANS radians}. + *

      + * Use {@code tanOf("angle", DEGREES)} as shortcut for + * + *

      +		 * { $tan : { $degreesToRadians : "$angle" } }
      +		 * 
      + * + * . + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link Tan}. + */ + public static Tan tanOf(String fieldReference) { + return tanOf(fieldReference, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Tan}. + */ + public static Tan tanOf(String fieldReference, AngularDimension unit) { + return tan(Fields.field(fieldReference), unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link Tan}. + */ + public static Tan tanOf(AggregationExpression expression) { + return tanOf(expression, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Tan}. + */ + public static Tan tanOf(AggregationExpression expression, AngularDimension unit) { + return tan(expression, unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value + * @return new instance of {@link Tan}. + */ + public static Tan tan(Object value) { + return tan(value, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Tan}. + */ + public static Tan tan(Object value, AngularDimension unit) { + + if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + return new Tan(ConvertOperators.DegreesToRadians.degreesToRadians(value)); + } + return new Tan(value); + } + + @Override + protected String getMongoMethod() { + return "$tan"; + } + } + + /** + * An {@link AggregationExpression expression} that calculates the hyperbolic tangent of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Tanh extends AbstractAggregationExpression { + + private Tanh(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link Tanh}. + */ + public static Tanh tanhOf(String fieldReference) { + return tanhOf(fieldReference, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * the given {@link AngularDimension unit}. + *

      + * Use {@code tanhOf("angle", DEGREES)} as shortcut for + * + *

      +		 * { $tanh : { $degreesToRadians : "$angle" } }
      +		 * 
      + * + * . + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Tanh}. + */ + public static Tanh tanhOf(String fieldReference, AngularDimension unit) { + return tanh(Fields.field(fieldReference), unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * {@link AngularDimension#RADIANS}. + *

      + * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. + * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link Tanh}. + */ + public static Tanh tanhOf(AggregationExpression expression) { + return tanhOf(expression, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * the given {@link AngularDimension unit}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Tanh}. + */ + public static Tanh tanhOf(AggregationExpression expression, AngularDimension unit) { + return tanh(expression, unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link Tanh}. + */ + public static Tanh tanh(Object value) { + return tanh(value, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * the given {@link AngularDimension unit}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Tanh}. + */ + public static Tanh tanh(Object value, AngularDimension unit) { + + if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + return new Tanh(ConvertOperators.DegreesToRadians.degreesToRadians(value)); + } + return new Tanh(value); + } + + @Override + protected String getMongoMethod() { + return "$tanh"; + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 9ee12be1eb..a2d011d6ad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -95,6 +95,8 @@ public class MethodReferenceNode extends ExpressionNode { map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit")); map.put("sin", singleArgRef().forOperator("$sin")); map.put("sinh", singleArgRef().forOperator("$sinh")); + map.put("tan", singleArgRef().forOperator("$tan")); + map.put("tanh", singleArgRef().forOperator("$tanh")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index cc32a94323..9a77d093c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -109,4 +109,33 @@ void rendersSinhWithValueInDegrees() { assertThat(valueOf("angle").sinh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(Document.parse("{ $sinh : { $degreesToRadians : \"$angle\" } }")); } + + @Test // GH-3730 + void rendersTan() { + + assertThat(valueOf("angle").tan().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $tan : \"$angle\" }")); + } + + @Test // GH-3730 + void rendersTanWithValueInDegrees() { + + assertThat(valueOf("angle").tan(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $tan : { $degreesToRadians : \"$angle\" } }")); + } + + @Test // GH-3730 + void rendersTanh() { + + assertThat(valueOf("angle").tanh().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $tanh : \"$angle\" }")); + } + + @Test // GH-3730 + void rendersTanhWithValueInDegrees() { + + assertThat(valueOf("angle").tanh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $tanh : { $degreesToRadians : \"$angle\" } }")); + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index e250241558..cc59a91700 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1014,6 +1014,16 @@ void shouldRenderSinh() { assertThat(transform("sinh(angle)")).isEqualTo(Document.parse("{ \"$sinh\" : \"$angle\"}")); } + @Test // GH-3730 + void shouldRenderTan() { + assertThat(transform("tan(angle)")).isEqualTo(Document.parse("{ \"$tan\" : \"$angle\"}")); + } + + @Test // GH-3730 + void shouldRenderTanh() { + assertThat(transform("tanh(angle)")).isEqualTo(Document.parse("{ \"$tanh\" : \"$angle\"}")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From c4c6267d91b89fd299f47a1a8604d86e9e87e53d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 28 Jul 2021 10:04:29 +0200 Subject: [PATCH 0504/1381] Add support for `$cos` and `$cosh` aggregation operators. Closes: #3710 Original pull request: #3755. --- .../core/aggregation/ArithmeticOperators.java | 251 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 2 + .../ArithmeticOperatorsUnitTests.java | 28 ++ .../SpelExpressionTransformerUnitTests.java | 10 + 4 files changed, 291 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index e26e41f651..4de258b4eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -719,6 +719,51 @@ public Sinh sinh(AngularDimension unit) { return usesFieldRef() ? Sinh.sinhOf(fieldReference, unit) : Sinh.sinhOf(expression, unit); } + /** + * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value given in + * {@link AngularDimension#RADIANS radians}. + * + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Cos cos() { + return cos(AngularDimension.RADIANS); + } + + /** + * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value in the given + * {@link AngularDimension unit}. + * + * @param unit the unit of measure. + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Cos cos(AngularDimension unit) { + return usesFieldRef() ? Cos.cosOf(fieldReference, unit) : Cos.cosOf(expression, unit); + } + + /** + * Creates new {@link AggregationExpression} that calculates the hyperbolic cosine of a numeric value given in + * {@link AngularDimension#RADIANS radians}. + * + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Cosh cosh() { + return cosh(AngularDimension.RADIANS); + } + + /** + * Creates new {@link AggregationExpression} that calculates the hyperbolic cosine of a numeric value. + * + * @param unit the unit of measure. + * @return new instance of {@link Sin}. + * @since 3.3 + */ + public Cosh cosh(AngularDimension unit) { + return usesFieldRef() ? Cosh.coshOf(fieldReference, unit) : Cosh.coshOf(expression, unit); + } + /** * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value given in * {@link AngularDimension#RADIANS radians}. @@ -2199,6 +2244,212 @@ protected String getMongoMethod() { } } + /** + * An {@link AggregationExpression expression} that calculates the cosine of a value that is measured in radians. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Cos extends AbstractAggregationExpression { + + private Cos(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in + * {@link AngularDimension#RADIANS radians}. + *

      + * Use {@code cosOf("angle", DEGREES)} as shortcut for + * + *

      +		 * { $cos : { $degreesToRadians : "$angle" } }
      +		 * 
      + * + * . + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link Cos}. + */ + public static Cos cosOf(String fieldReference) { + return cosOf(fieldReference, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Cos}. + */ + public static Cos cosOf(String fieldReference, AngularDimension unit) { + return cos(Fields.field(fieldReference), unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link Cos}. + */ + public static Cos cosOf(AggregationExpression expression) { + return cosOf(expression, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Cos}. + */ + public static Cos cosOf(AggregationExpression expression, AngularDimension unit) { + return cos(expression, unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value + * @return new instance of {@link Cos}. + */ + public static Cos cos(Object value) { + return cos(value, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in the given + * {@link AngularDimension unit}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Cos}. + */ + public static Cos cos(Object value, AngularDimension unit) { + + if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + return new Cos(ConvertOperators.DegreesToRadians.degreesToRadians(value)); + } + return new Cos(value); + } + + @Override + protected String getMongoMethod() { + return "$cos"; + } + } + + /** + * An {@link AggregationExpression expression} that calculates the hyperbolic cosine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class Cosh extends AbstractAggregationExpression { + + private Cosh(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link Cosh}. + */ + public static Cosh coshOf(String fieldReference) { + return coshOf(fieldReference, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in + * the given {@link AngularDimension unit}. + *

      + * Use {@code coshOf("angle", DEGREES)} as shortcut for + * + *

      +		 * { $cosh : { $degreesToRadians : "$angle" } }
      +		 * 
      + * + * . + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Cosh}. + */ + public static Cosh coshOf(String fieldReference, AngularDimension unit) { + return cosh(Fields.field(fieldReference), unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in + * {@link AngularDimension#RADIANS}. + *

      + * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. + * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link Cosh}. + */ + public static Cosh coshOf(AggregationExpression expression) { + return coshOf(expression, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in + * the given {@link AngularDimension unit}. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Cosh}. + */ + public static Cosh coshOf(AggregationExpression expression, AngularDimension unit) { + return cosh(expression, unit); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in + * {@link AngularDimension#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link Cosh}. + */ + public static Cosh cosh(Object value) { + return cosh(value, AngularDimension.RADIANS); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in + * the given {@link AngularDimension unit}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value + * @param unit the unit of measure used by the value of the given field. + * @return new instance of {@link Cosh}. + */ + public static Cosh cosh(Object value, AngularDimension unit) { + + if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + return new Cosh(ConvertOperators.DegreesToRadians.degreesToRadians(value)); + } + return new Cosh(value); + } + + @Override + protected String getMongoMethod() { + return "$cosh"; + } + } + /** * An {@link AggregationExpression expression} that calculates the tangent of a value that is measured in radians. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index a2d011d6ad..1efe94c757 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -95,6 +95,8 @@ public class MethodReferenceNode extends ExpressionNode { map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit")); map.put("sin", singleArgRef().forOperator("$sin")); map.put("sinh", singleArgRef().forOperator("$sinh")); + map.put("cos", singleArgRef().forOperator("$cos")); + map.put("cosh", singleArgRef().forOperator("$cosh")); map.put("tan", singleArgRef().forOperator("$tan")); map.put("tanh", singleArgRef().forOperator("$tanh")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 9a77d093c4..55d1647568 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -110,6 +110,34 @@ void rendersSinhWithValueInDegrees() { .isEqualTo(Document.parse("{ $sinh : { $degreesToRadians : \"$angle\" } }")); } + @Test // GH-3710 + void rendersCos() { + + assertThat(valueOf("angle").cos().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $cos : \"$angle\" }")); + } + + @Test // GH-3710 + void rendersCosWithValueInDegrees() { + + assertThat(valueOf("angle").cos(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $cos : { $degreesToRadians : \"$angle\" } }")); + } + + @Test // GH-3710 + void rendersCosh() { + + assertThat(valueOf("angle").cosh().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $cosh : \"$angle\" }")); + } + + @Test // GH-3710 + void rendersCoshWithValueInDegrees() { + + assertThat(valueOf("angle").cosh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $cosh : { $degreesToRadians : \"$angle\" } }")); + } + @Test // GH-3730 void rendersTan() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index cc59a91700..e30f7f9fb9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1014,6 +1014,16 @@ void shouldRenderSinh() { assertThat(transform("sinh(angle)")).isEqualTo(Document.parse("{ \"$sinh\" : \"$angle\"}")); } + @Test // GH-3710 + void shouldRenderCos() { + assertThat(transform("cos(angle)")).isEqualTo(Document.parse("{ \"$cos\" : \"$angle\"}")); + } + + @Test // GH-3710 + void shouldRenderCosh() { + assertThat(transform("cosh(angle)")).isEqualTo(Document.parse("{ \"$cosh\" : \"$angle\"}")); + } + @Test // GH-3730 void shouldRenderTan() { assertThat(transform("tan(angle)")).isEqualTo(Document.parse("{ \"$tan\" : \"$angle\"}")); From df0372eee1368a5b0c03de1ad3bda9e1aaecf9e7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 24 Aug 2021 16:11:53 +0200 Subject: [PATCH 0505/1381] Polishing. Rename AngularDimension to AngularUnit. Tweak Javadoc. Simplify tests. Update reference docs. See: #3710, #3714, #3728, #3730 Original pull request: #3755. --- .../core/aggregation/ArithmeticOperators.java | 244 ++++++----- .../core/aggregation/ConvertOperators.java | 3 +- .../ArithmeticOperatorsUnitTests.java | 36 +- .../SpelExpressionTransformerUnitTests.java | 402 +++++++++--------- .../reference/aggregation-framework.adoc | 4 +- 5 files changed, 355 insertions(+), 334 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 4de258b4eb..7896486abf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -678,34 +678,37 @@ public Round roundToPlace(int place) { } /** - * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in {@link AngularDimension#RADIANS radians}. + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in + * {@link AngularUnit#RADIANS radians}. * * @return new instance of {@link Sin}. * @since 3.3 */ public Sin sin() { - return sin(AngularDimension.RADIANS); + return sin(AngularUnit.RADIANS); } /** - * Creates new {@link AggregationExpression} that calculates the sine of a numeric value in the given {@link AngularDimension unit}. + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value in the given + * {@link AngularUnit unit}. * * @param unit the unit of measure. * @return new instance of {@link Sin}. * @since 3.3 */ - public Sin sin(AngularDimension unit) { + public Sin sin(AngularUnit unit) { return usesFieldRef() ? Sin.sinOf(fieldReference, unit) : Sin.sinOf(expression, unit); } /** - * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in {@link AngularDimension#RADIANS radians}. + * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in + * {@link AngularUnit#RADIANS radians}. * * @return new instance of {@link Sin}. * @since 3.3 */ public Sinh sinh() { - return sinh(AngularDimension.RADIANS); + return sinh(AngularUnit.RADIANS); } /** @@ -715,42 +718,42 @@ public Sinh sinh() { * @return new instance of {@link Sin}. * @since 3.3 */ - public Sinh sinh(AngularDimension unit) { + public Sinh sinh(AngularUnit unit) { return usesFieldRef() ? Sinh.sinhOf(fieldReference, unit) : Sinh.sinhOf(expression, unit); } /** * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value given in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. * * @return new instance of {@link Sin}. * @since 3.3 */ public Cos cos() { - return cos(AngularDimension.RADIANS); + return cos(AngularUnit.RADIANS); } /** * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param unit the unit of measure. * @return new instance of {@link Sin}. * @since 3.3 */ - public Cos cos(AngularDimension unit) { + public Cos cos(AngularUnit unit) { return usesFieldRef() ? Cos.cosOf(fieldReference, unit) : Cos.cosOf(expression, unit); } /** * Creates new {@link AggregationExpression} that calculates the hyperbolic cosine of a numeric value given in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. * * @return new instance of {@link Sin}. * @since 3.3 */ public Cosh cosh() { - return cosh(AngularDimension.RADIANS); + return cosh(AngularUnit.RADIANS); } /** @@ -760,42 +763,42 @@ public Cosh cosh() { * @return new instance of {@link Sin}. * @since 3.3 */ - public Cosh cosh(AngularDimension unit) { + public Cosh cosh(AngularUnit unit) { return usesFieldRef() ? Cosh.coshOf(fieldReference, unit) : Cosh.coshOf(expression, unit); } /** * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value given in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. * * @return new instance of {@link Sin}. * @since 3.3 */ public Tan tan() { - return tan(AngularDimension.RADIANS); + return tan(AngularUnit.RADIANS); } /** * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param unit the unit of measure. * @return new instance of {@link Sin}. * @since 3.3 */ - public Tan tan(AngularDimension unit) { + public Tan tan(AngularUnit unit) { return usesFieldRef() ? Tan.tanOf(fieldReference, unit) : Tan.tanOf(expression, unit); } /** * Creates new {@link AggregationExpression} that calculates the hyperbolic tangent of a numeric value given in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. * * @return new instance of {@link Sin}. * @since 3.3 */ public Tanh tanh() { - return tanh(AngularDimension.RADIANS); + return tanh(AngularUnit.RADIANS); } /** @@ -805,7 +808,7 @@ public Tanh tanh() { * @return new instance of {@link Sin}. * @since 3.3 */ - public Tanh tanh(AngularDimension unit) { + public Tanh tanh(AngularUnit unit) { return usesFieldRef() ? Tanh.tanhOf(fieldReference, unit) : Tanh.tanhOf(expression, unit); } @@ -2047,7 +2050,7 @@ protected String getMongoMethod() { * @author Christoph Strobl * @since 3.3 */ - public enum AngularDimension { + public enum AngularUnit { RADIANS, DEGREES } @@ -2065,76 +2068,82 @@ private Sin(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. *

      - * Use {@code sinhOf("angle", DEGREES)} as shortcut for

      { $sinh : { $degreesToRadians : "$angle" } }
      . + * Use {@code sinhOf("angle", DEGREES)} as shortcut for + * + *
      +		 * { $sinh : { $degreesToRadians : "$angle" } }
      +		 * 
      + * + * . * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Sin}. */ public static Sin sinOf(String fieldReference) { - return sinOf(fieldReference, AngularDimension.RADIANS); + return sinOf(fieldReference, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Sin}. */ - public static Sin sinOf(String fieldReference, AngularDimension unit) { + public static Sin sinOf(String fieldReference, AngularUnit unit) { return sin(Fields.field(fieldReference), unit); } /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link Sin}. */ public static Sin sinOf(AggregationExpression expression) { - return sinOf(expression, AngularDimension.RADIANS); + return sinOf(expression, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Sin}. */ - public static Sin sinOf(AggregationExpression expression, AngularDimension unit) { + public static Sin sinOf(AggregationExpression expression, AngularUnit unit) { return sin(expression, unit); } /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value * @return new instance of {@link Sin}. */ public static Sin sin(Object value) { - return sin(value, AngularDimension.RADIANS); + return sin(value, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Sin}. */ - public static Sin sin(Object value, AngularDimension unit) { + public static Sin sin(Object value, AngularUnit unit) { - if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + if (ObjectUtils.nullSafeEquals(AngularUnit.DEGREES, unit)) { return new Sin(ConvertOperators.DegreesToRadians.degreesToRadians(value)); } return new Sin(value); @@ -2148,7 +2157,7 @@ protected String getMongoMethod() { /** * An {@link AggregationExpression expression} that calculates the hyperbolic sine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @author Christoph Strobl * @since 3.3 @@ -2161,78 +2170,85 @@ private Sinh(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Sin}. */ public static Sinh sinhOf(String fieldReference) { - return sinhOf(fieldReference, AngularDimension.RADIANS); + return sinhOf(fieldReference, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. *

      - * Use {@code sinhOf("angle", DEGREES)} as shortcut for

      { $sinh : { $degreesToRadians : "$angle" } }
      . + * Use {@code sinhOf("angle", DEGREES)} as shortcut for + * + *
      +		 * { $sinh : { $degreesToRadians : "$angle" } }
      +		 * 
      + * + * . * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Sin}. */ - public static Sinh sinhOf(String fieldReference, AngularDimension unit) { + public static Sinh sinhOf(String fieldReference, AngularUnit unit) { return sinh(Fields.field(fieldReference), unit); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. *

      - * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. + * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. + * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link Sin}. */ public static Sinh sinhOf(AggregationExpression expression) { - return sinhOf(expression, AngularDimension.RADIANS); + return sinhOf(expression, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Sin}. */ - public static Sinh sinhOf(AggregationExpression expression, AngularDimension unit) { + public static Sinh sinhOf(AggregationExpression expression, AngularUnit unit) { return sinh(expression, unit); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value. * @return new instance of {@link Sin}. */ public static Sinh sinh(Object value) { - return sinh(value, AngularDimension.RADIANS); + return sinh(value, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Sin}. */ - public static Sinh sinh(Object value, AngularDimension unit) { + public static Sinh sinh(Object value, AngularUnit unit) { - if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + if (ObjectUtils.nullSafeEquals(AngularUnit.DEGREES, unit)) { return new Sinh(ConvertOperators.DegreesToRadians.degreesToRadians(value)); } return new Sinh(value); @@ -2258,82 +2274,82 @@ private Cos(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. *

      * Use {@code cosOf("angle", DEGREES)} as shortcut for - * + * *

       		 * { $cos : { $degreesToRadians : "$angle" } }
       		 * 
      - * + * * . * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Cos}. */ public static Cos cosOf(String fieldReference) { - return cosOf(fieldReference, AngularDimension.RADIANS); + return cosOf(fieldReference, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cos}. */ - public static Cos cosOf(String fieldReference, AngularDimension unit) { + public static Cos cosOf(String fieldReference, AngularUnit unit) { return cos(Fields.field(fieldReference), unit); } /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link Cos}. */ public static Cos cosOf(AggregationExpression expression) { - return cosOf(expression, AngularDimension.RADIANS); + return cosOf(expression, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cos}. */ - public static Cos cosOf(AggregationExpression expression, AngularDimension unit) { + public static Cos cosOf(AggregationExpression expression, AngularUnit unit) { return cos(expression, unit); } /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value * @return new instance of {@link Cos}. */ public static Cos cos(Object value) { - return cos(value, AngularDimension.RADIANS); + return cos(value, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cos}. */ - public static Cos cos(Object value, AngularDimension unit) { + public static Cos cos(Object value, AngularUnit unit) { - if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + if (ObjectUtils.nullSafeEquals(AngularUnit.DEGREES, unit)) { return new Cos(ConvertOperators.DegreesToRadians.degreesToRadians(value)); } return new Cos(value); @@ -2347,7 +2363,7 @@ protected String getMongoMethod() { /** * An {@link AggregationExpression expression} that calculates the hyperbolic cosine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @author Christoph Strobl * @since 3.3 @@ -2360,38 +2376,38 @@ private Cosh(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Cosh}. */ public static Cosh coshOf(String fieldReference) { - return coshOf(fieldReference, AngularDimension.RADIANS); + return coshOf(fieldReference, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. *

      * Use {@code coshOf("angle", DEGREES)} as shortcut for - * + * *

       		 * { $cosh : { $degreesToRadians : "$angle" } }
       		 * 
      - * + * * . * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cosh}. */ - public static Cosh coshOf(String fieldReference, AngularDimension unit) { + public static Cosh coshOf(String fieldReference, AngularUnit unit) { return cosh(Fields.field(fieldReference), unit); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. *

      * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. @@ -2400,45 +2416,45 @@ public static Cosh coshOf(String fieldReference, AngularDimension unit) { * @return new instance of {@link Cosh}. */ public static Cosh coshOf(AggregationExpression expression) { - return coshOf(expression, AngularDimension.RADIANS); + return coshOf(expression, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cosh}. */ - public static Cosh coshOf(AggregationExpression expression, AngularDimension unit) { + public static Cosh coshOf(AggregationExpression expression, AngularUnit unit) { return cosh(expression, unit); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value. * @return new instance of {@link Cosh}. */ public static Cosh cosh(Object value) { - return cosh(value, AngularDimension.RADIANS); + return cosh(value, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cosh}. */ - public static Cosh cosh(Object value, AngularDimension unit) { + public static Cosh cosh(Object value, AngularUnit unit) { - if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + if (ObjectUtils.nullSafeEquals(AngularUnit.DEGREES, unit)) { return new Cosh(ConvertOperators.DegreesToRadians.degreesToRadians(value)); } return new Cosh(value); @@ -2464,82 +2480,82 @@ private Tan(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in - * {@link AngularDimension#RADIANS radians}. + * {@link AngularUnit#RADIANS radians}. *

      * Use {@code tanOf("angle", DEGREES)} as shortcut for - * + * *

       		 * { $tan : { $degreesToRadians : "$angle" } }
       		 * 
      - * + * * . * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Tan}. */ public static Tan tanOf(String fieldReference) { - return tanOf(fieldReference, AngularDimension.RADIANS); + return tanOf(fieldReference, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tan}. */ - public static Tan tanOf(String fieldReference, AngularDimension unit) { + public static Tan tanOf(String fieldReference, AngularUnit unit) { return tan(Fields.field(fieldReference), unit); } /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link Tan}. */ public static Tan tanOf(AggregationExpression expression) { - return tanOf(expression, AngularDimension.RADIANS); + return tanOf(expression, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tan}. */ - public static Tan tanOf(AggregationExpression expression, AngularDimension unit) { + public static Tan tanOf(AggregationExpression expression, AngularUnit unit) { return tan(expression, unit); } /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value * @return new instance of {@link Tan}. */ public static Tan tan(Object value) { - return tan(value, AngularDimension.RADIANS); + return tan(value, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in the given - * {@link AngularDimension unit}. + * {@link AngularUnit unit}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tan}. */ - public static Tan tan(Object value, AngularDimension unit) { + public static Tan tan(Object value, AngularUnit unit) { - if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + if (ObjectUtils.nullSafeEquals(AngularUnit.DEGREES, unit)) { return new Tan(ConvertOperators.DegreesToRadians.degreesToRadians(value)); } return new Tan(value); @@ -2553,7 +2569,7 @@ protected String getMongoMethod() { /** * An {@link AggregationExpression expression} that calculates the hyperbolic tangent of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @author Christoph Strobl * @since 3.3 @@ -2566,38 +2582,38 @@ private Tanh(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Tanh}. */ public static Tanh tanhOf(String fieldReference) { - return tanhOf(fieldReference, AngularDimension.RADIANS); + return tanhOf(fieldReference, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. *

      * Use {@code tanhOf("angle", DEGREES)} as shortcut for - * + * *

       		 * { $tanh : { $degreesToRadians : "$angle" } }
       		 * 
      - * + * * . * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tanh}. */ - public static Tanh tanhOf(String fieldReference, AngularDimension unit) { + public static Tanh tanhOf(String fieldReference, AngularUnit unit) { return tanh(Fields.field(fieldReference), unit); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. *

      * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. @@ -2606,45 +2622,45 @@ public static Tanh tanhOf(String fieldReference, AngularDimension unit) { * @return new instance of {@link Tanh}. */ public static Tanh tanhOf(AggregationExpression expression) { - return tanhOf(expression, AngularDimension.RADIANS); + return tanhOf(expression, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tanh}. */ - public static Tanh tanhOf(AggregationExpression expression, AngularDimension unit) { + public static Tanh tanhOf(AggregationExpression expression, AngularUnit unit) { return tanh(expression, unit); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in - * {@link AngularDimension#RADIANS}. + * {@link AngularUnit#RADIANS}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value. * @return new instance of {@link Tanh}. */ public static Tanh tanh(Object value) { - return tanh(value, AngularDimension.RADIANS); + return tanh(value, AngularUnit.RADIANS); } /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in - * the given {@link AngularDimension unit}. + * the given {@link AngularUnit unit}. * * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a * numeric value * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tanh}. */ - public static Tanh tanh(Object value, AngularDimension unit) { + public static Tanh tanh(Object value, AngularUnit unit) { - if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) { + if (ObjectUtils.nullSafeEquals(AngularUnit.DEGREES, unit)) { return new Tanh(ConvertOperators.DegreesToRadians.degreesToRadians(value)); } return new Tanh(value); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java index b34933444a..637ebd8d8f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java @@ -232,7 +232,8 @@ public ToString convertToString() { } /** - * {@link AggregationExpression} for {@code $degreesToRadians} that converts an input value measured in degrees to radians.\ + * {@link AggregationExpression} for {@code $degreesToRadians} that converts an input value measured in degrees to + * radians. * * @return new instance of {@link DegreesToRadians}. * @since 3.3 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 55d1647568..7cde7cd1c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -86,84 +86,84 @@ void rendersIntegralWithUnit() { void rendersSin() { assertThat(valueOf("angle").sin().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $sin : \"$angle\" }")); + .isEqualTo("{ $sin : \"$angle\" }"); } @Test // GH-3728 void rendersSinWithValueInDegrees() { - assertThat(valueOf("angle").sin(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $sin : { $degreesToRadians : \"$angle\" } }")); + assertThat(valueOf("angle").sin(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $sin : { $degreesToRadians : \"$angle\" } }"); } @Test // GH-3728 void rendersSinh() { assertThat(valueOf("angle").sinh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $sinh : \"$angle\" }")); + .isEqualTo("{ $sinh : \"$angle\" }"); } @Test // GH-3728 void rendersSinhWithValueInDegrees() { - assertThat(valueOf("angle").sinh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $sinh : { $degreesToRadians : \"$angle\" } }")); + assertThat(valueOf("angle").sinh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $sinh : { $degreesToRadians : \"$angle\" } }"); } @Test // GH-3710 void rendersCos() { assertThat(valueOf("angle").cos().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $cos : \"$angle\" }")); + .isEqualTo("{ $cos : \"$angle\" }"); } @Test // GH-3710 void rendersCosWithValueInDegrees() { - assertThat(valueOf("angle").cos(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $cos : { $degreesToRadians : \"$angle\" } }")); + assertThat(valueOf("angle").cos(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $cos : { $degreesToRadians : \"$angle\" } }"); } @Test // GH-3710 void rendersCosh() { assertThat(valueOf("angle").cosh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $cosh : \"$angle\" }")); + .isEqualTo("{ $cosh : \"$angle\" }"); } @Test // GH-3710 void rendersCoshWithValueInDegrees() { - assertThat(valueOf("angle").cosh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $cosh : { $degreesToRadians : \"$angle\" } }")); + assertThat(valueOf("angle").cosh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $cosh : { $degreesToRadians : \"$angle\" } }"); } @Test // GH-3730 void rendersTan() { assertThat(valueOf("angle").tan().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $tan : \"$angle\" }")); + .isEqualTo("{ $tan : \"$angle\" }"); } @Test // GH-3730 void rendersTanWithValueInDegrees() { - assertThat(valueOf("angle").tan(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $tan : { $degreesToRadians : \"$angle\" } }")); + assertThat(valueOf("angle").tan(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $tan : { $degreesToRadians : \"$angle\" } }"); } @Test // GH-3730 void rendersTanh() { assertThat(valueOf("angle").tanh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $tanh : \"$angle\" }")); + .isEqualTo("{ $tanh : \"$angle\" }"); } @Test // GH-3730 void rendersTanhWithValueInDegrees() { - assertThat(valueOf("angle").tanh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $tanh : { $degreesToRadians : \"$angle\" } }")); + assertThat(valueOf("angle").tanh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $tanh : { $degreesToRadians : \"$angle\" } }"); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index e30f7f9fb9..193ffb520d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.mongodb.core.aggregation; -import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.test.util.Assertions.*; import java.util.Arrays; @@ -53,21 +53,21 @@ void beforeEach() { @Test // DATAMONGO-774 void shouldRenderConstantExpression() { - assertThat(transform("1")).isEqualTo("1"); - assertThat(transform("-1")).isEqualTo("-1"); - assertThat(transform("1.0")).isEqualTo("1.0"); - assertThat(transform("-1.0")).isEqualTo("-1.0"); - assertThat(transform("null")).isNull(); + assertThat(transformValue("1")).isEqualTo("1"); + assertThat(transformValue("-1")).isEqualTo("-1"); + assertThat(transformValue("1.0")).isEqualTo("1.0"); + assertThat(transformValue("-1.0")).isEqualTo("-1.0"); + assertThat(transformValue("null")).isNull(); } @Test // DATAMONGO-774 void shouldSupportKnownOperands() { - assertThat(transform("a + b")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a - b")).isEqualTo(Document.parse("{ \"$subtract\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a * b")).isEqualTo(Document.parse("{ \"$multiply\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a / b")).isEqualTo(Document.parse("{ \"$divide\" : [ \"$a\" , \"$b\"]}")); - assertThat(transform("a % b")).isEqualTo(Document.parse("{ \"$mod\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("a + b")).isEqualTo("{ \"$add\" : [ \"$a\" , \"$b\"]}"); + assertThat(transform("a - b")).isEqualTo("{ \"$subtract\" : [ \"$a\" , \"$b\"]}"); + assertThat(transform("a * b")).isEqualTo("{ \"$multiply\" : [ \"$a\" , \"$b\"]}"); + assertThat(transform("a / b")).isEqualTo("{ \"$divide\" : [ \"$a\" , \"$b\"]}"); + assertThat(transform("a % b")).isEqualTo("{ \"$mod\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-774 @@ -77,35 +77,35 @@ void shouldThrowExceptionOnUnknownOperand() { @Test // DATAMONGO-774 void shouldRenderSumExpression() { - assertThat(transform("a + 1")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a\" , 1]}")); + assertThat(transform("a + 1")).isEqualTo("{ \"$add\" : [ \"$a\" , 1]}"); } @Test // DATAMONGO-774 void shouldRenderFormula() { - assertThat(transform("(netPrice + surCharge) * taxrate + 42")).isEqualTo(Document.parse( - "{ \"$add\" : [ { \"$multiply\" : [ { \"$add\" : [ \"$netPrice\" , \"$surCharge\"]} , \"$taxrate\"]} , 42]}")); + assertThat(transform("(netPrice + surCharge) * taxrate + 42")).isEqualTo( + "{ \"$add\" : [ { \"$multiply\" : [ { \"$add\" : [ \"$netPrice\" , \"$surCharge\"]} , \"$taxrate\"]} , 42]}"); } @Test // DATAMONGO-774 void shouldRenderFormulaInCurlyBrackets() { - assertThat(transform("{(netPrice + surCharge) * taxrate + 42}")).isEqualTo(Document.parse( - "{ \"$add\" : [ { \"$multiply\" : [ { \"$add\" : [ \"$netPrice\" , \"$surCharge\"]} , \"$taxrate\"]} , 42]}")); + assertThat(transform("{(netPrice + surCharge) * taxrate + 42}")).isEqualTo( + "{ \"$add\" : [ { \"$multiply\" : [ { \"$add\" : [ \"$netPrice\" , \"$surCharge\"]} , \"$taxrate\"]} , 42]}"); } @Test // DATAMONGO-774 void shouldRenderFieldReference() { - assertThat(transform("foo")).isEqualTo("$foo"); - assertThat(transform("$foo")).isEqualTo("$foo"); + assertThat(transformValue("foo")).isEqualTo("$foo"); + assertThat(transformValue("$foo")).isEqualTo("$foo"); } @Test // DATAMONGO-774 void shouldRenderNestedFieldReference() { - assertThat(transform("foo.bar")).isEqualTo("$foo.bar"); - assertThat(transform("$foo.bar")).isEqualTo("$foo.bar"); + assertThat(transformValue("foo.bar")).isEqualTo("$foo.bar"); + assertThat(transformValue("$foo.bar")).isEqualTo("$foo.bar"); } @Test // DATAMONGO-774 @@ -113,52 +113,52 @@ void shouldRenderNestedFieldReference() { void shouldRenderNestedIndexedFieldReference() { // TODO add support for rendering nested indexed field references - assertThat(transform("foo[3].bar")).isEqualTo("$foo[3].bar"); + assertThat(transformValue("foo[3].bar")).isEqualTo("$foo[3].bar"); } @Test // DATAMONGO-774 void shouldRenderConsecutiveOperation() { - assertThat(transform("1 + 1 + 1")).isEqualTo(Document.parse("{ \"$add\" : [ 1 , 1 , 1]}")); + assertThat(transform("1 + 1 + 1")).isEqualTo("{ \"$add\" : [ 1 , 1 , 1]}"); } @Test // DATAMONGO-774 void shouldRenderComplexExpression0() { assertThat(transform("-(1 + q)")) - .isEqualTo(Document.parse("{ \"$multiply\" : [ -1 , { \"$add\" : [ 1 , \"$q\"]}]}")); + .isEqualTo("{ \"$multiply\" : [ -1 , { \"$add\" : [ 1 , \"$q\"]}]}"); } @Test // DATAMONGO-774 void shouldRenderComplexExpression1() { - assertThat(transform("1 + (q + 1) / (q - 1)")).isEqualTo(Document.parse( - "{ \"$add\" : [ 1 , { \"$divide\" : [ { \"$add\" : [ \"$q\" , 1]} , { \"$subtract\" : [ \"$q\" , 1]}]}]}")); + assertThat(transform("1 + (q + 1) / (q - 1)")).isEqualTo( + "{ \"$add\" : [ 1 , { \"$divide\" : [ { \"$add\" : [ \"$q\" , 1]} , { \"$subtract\" : [ \"$q\" , 1]}]}]}"); } @Test // DATAMONGO-774 void shouldRenderComplexExpression2() { - assertThat(transform("(q + 1 + 4 - 5) / (q + 1 + 3 + 4)")).isEqualTo(Document.parse( - "{ \"$divide\" : [ { \"$subtract\" : [ { \"$add\" : [ \"$q\" , 1 , 4]} , 5]} , { \"$add\" : [ \"$q\" , 1 , 3 , 4]}]}")); + assertThat(transform("(q + 1 + 4 - 5) / (q + 1 + 3 + 4)")).isEqualTo( + "{ \"$divide\" : [ { \"$subtract\" : [ { \"$add\" : [ \"$q\" , 1 , 4]} , 5]} , { \"$add\" : [ \"$q\" , 1 , 3 , 4]}]}"); } @Test // DATAMONGO-774 void shouldRenderBinaryExpressionWithMixedSignsCorrectly() { - assertThat(transform("-4 + 1")).isEqualTo(Document.parse("{ \"$add\" : [ -4 , 1]}")); - assertThat(transform("1 + -4")).isEqualTo(Document.parse("{ \"$add\" : [ 1 , -4]}")); + assertThat(transform("-4 + 1")).isEqualTo("{ \"$add\" : [ -4 , 1]}"); + assertThat(transform("1 + -4")).isEqualTo("{ \"$add\" : [ 1 , -4]}"); } @Test // DATAMONGO-774 void shouldRenderConsecutiveOperationsInComplexExpression() { assertThat(transform("1 + 1 + (1 + 1 + 1) / q")) - .isEqualTo(Document.parse("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}")); + .isEqualTo("{ \"$add\" : [ 1 , 1 , { \"$divide\" : [ { \"$add\" : [ 1 , 1 , 1]} , \"$q\"]}]}"); } @Test // DATAMONGO-774 void shouldRenderParameterExpressionResults() { - assertThat(transform("[0] + [1] + [2]", 1, 2, 3)).isEqualTo(Document.parse("{ \"$add\" : [ 1 , 2 , 3]}")); + assertThat(transform("[0] + [1] + [2]", 1, 2, 3)).isEqualTo("{ \"$add\" : [ 1 , 2 , 3]}"); } @Test // DATAMONGO-774 @@ -189,852 +189,856 @@ void shouldRenderCompoundExpressionsWithIndexerAndFieldReference() { Person person = new Person(); person.setAge(10); - assertThat(transform("[0].age + a.c", person)).isEqualTo(Document.parse("{ \"$add\" : [ 10 , \"$a.c\"] }")); + assertThat(transform("[0].age + a.c", person)).isEqualTo("{ \"$add\" : [ 10 , \"$a.c\"] }"); } @Test // DATAMONGO-840 void shouldRenderCompoundExpressionsWithOnlyFieldReferences() { - assertThat(transform("a.b + a.c")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a.b\" , \"$a.c\"]}")); + assertThat(transform("a.b + a.c")).isEqualTo("{ \"$add\" : [ \"$a.b\" , \"$a.c\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeAnd() { - assertThat(transform("and(a, b)")).isEqualTo(Document.parse("{ \"$and\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("and(a, b)")).isEqualTo("{ \"$and\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeOr() { - assertThat(transform("or(a, b)")).isEqualTo(Document.parse("{ \"$or\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("or(a, b)")).isEqualTo("{ \"$or\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeNot() { - assertThat(transform("not(a)")).isEqualTo(Document.parse("{ \"$not\" : [ \"$a\"]}")); + assertThat(transform("not(a)")).isEqualTo("{ \"$not\" : [ \"$a\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSetEquals() { - assertThat(transform("setEquals(a, b)")).isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("setEquals(a, b)")).isEqualTo("{ \"$setEquals\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSetEqualsForArrays() { assertThat(transform("setEquals(new int[]{1,2,3}, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$setEquals\" : [ [ 1 , 2 , 3] , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$setEquals\" : [ [ 1 , 2 , 3] , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSetEqualsMixedArrays() { assertThat(transform("setEquals(a, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$setEquals\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$setEquals\" : [ \"$a\" , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceSetIntersection() { assertThat(transform("setIntersection(a, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$setIntersection\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$setIntersection\" : [ \"$a\" , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceSetUnion() { assertThat(transform("setUnion(a, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$setUnion\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$setUnion\" : [ \"$a\" , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceSeDifference() { assertThat(transform("setDifference(a, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$setDifference\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$setDifference\" : [ \"$a\" , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceSetIsSubset() { assertThat(transform("setIsSubset(a, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$setIsSubset\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$setIsSubset\" : [ \"$a\" , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceAnyElementTrue() { - assertThat(transform("anyElementTrue(a)")).isEqualTo(Document.parse("{ \"$anyElementTrue\" : [ \"$a\"]}")); + assertThat(transform("anyElementTrue(a)")).isEqualTo("{ \"$anyElementTrue\" : [ \"$a\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceAllElementsTrue() { assertThat(transform("allElementsTrue(a, new int[]{4,5,6})")) - .isEqualTo(Document.parse("{ \"$allElementsTrue\" : [ \"$a\" , [ 4 , 5 , 6]]}")); + .isEqualTo("{ \"$allElementsTrue\" : [ \"$a\" , [ 4 , 5 , 6]]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceCmp() { - assertThat(transform("cmp(a, 250)")).isEqualTo(Document.parse("{ \"$cmp\" : [ \"$a\" , 250]}")); + assertThat(transform("cmp(a, 250)")).isEqualTo("{ \"$cmp\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceEq() { - assertThat(transform("eq(a, 250)")).isEqualTo(Document.parse("{ \"$eq\" : [ \"$a\" , 250]}")); + assertThat(transform("eq(a, 250)")).isEqualTo("{ \"$eq\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceGt() { - assertThat(transform("gt(a, 250)")).isEqualTo(Document.parse("{ \"$gt\" : [ \"$a\" , 250]}")); + assertThat(transform("gt(a, 250)")).isEqualTo("{ \"$gt\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceGte() { - assertThat(transform("gte(a, 250)")).isEqualTo(Document.parse("{ \"$gte\" : [ \"$a\" , 250]}")); + assertThat(transform("gte(a, 250)")).isEqualTo("{ \"$gte\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLt() { - assertThat(transform("lt(a, 250)")).isEqualTo(Document.parse("{ \"$lt\" : [ \"$a\" , 250]}")); + assertThat(transform("lt(a, 250)")).isEqualTo("{ \"$lt\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLte() { - assertThat(transform("lte(a, 250)")).isEqualTo(Document.parse("{ \"$lte\" : [ \"$a\" , 250]}")); + assertThat(transform("lte(a, 250)")).isEqualTo("{ \"$lte\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNe() { - assertThat(transform("ne(a, 250)")).isEqualTo(Document.parse("{ \"$ne\" : [ \"$a\" , 250]}")); + assertThat(transform("ne(a, 250)")).isEqualTo("{ \"$ne\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceAbs() { - assertThat(transform("abs(1)")).isEqualTo(Document.parse("{ \"$abs\" : 1}")); + assertThat(transform("abs(1)")).isEqualTo("{ \"$abs\" : 1}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceAdd() { - assertThat(transform("add(a, 250)")).isEqualTo(Document.parse("{ \"$add\" : [ \"$a\" , 250]}")); + assertThat(transform("add(a, 250)")).isEqualTo("{ \"$add\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceCeil() { - assertThat(transform("ceil(7.8)")).isEqualTo(Document.parse("{ \"$ceil\" : 7.8}")); + assertThat(transform("ceil(7.8)")).isEqualTo("{ \"$ceil\" : 7.8}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceDivide() { - assertThat(transform("divide(a, 250)")).isEqualTo(Document.parse("{ \"$divide\" : [ \"$a\" , 250]}")); + assertThat(transform("divide(a, 250)")).isEqualTo("{ \"$divide\" : [ \"$a\" , 250]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceExp() { - assertThat(transform("exp(2)")).isEqualTo(Document.parse("{ \"$exp\" : 2}")); + assertThat(transform("exp(2)")).isEqualTo("{ \"$exp\" : 2}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceFloor() { - assertThat(transform("floor(2)")).isEqualTo(Document.parse("{ \"$floor\" : 2}")); + assertThat(transform("floor(2)")).isEqualTo("{ \"$floor\" : 2}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLn() { - assertThat(transform("ln(2)")).isEqualTo(Document.parse("{ \"$ln\" : 2}")); + assertThat(transform("ln(2)")).isEqualTo("{ \"$ln\" : 2}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLog() { - assertThat(transform("log(100, 10)")).isEqualTo(Document.parse("{ \"$log\" : [ 100 , 10]}")); + assertThat(transform("log(100, 10)")).isEqualTo("{ \"$log\" : [ 100 , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLog10() { - assertThat(transform("log10(100)")).isEqualTo(Document.parse("{ \"$log10\" : 100}")); + assertThat(transform("log10(100)")).isEqualTo("{ \"$log10\" : 100}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeMod() { - assertThat(transform("mod(a, b)")).isEqualTo(Document.parse("{ \"$mod\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("mod(a, b)")).isEqualTo("{ \"$mod\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeMultiply() { - assertThat(transform("multiply(a, b)")).isEqualTo(Document.parse("{ \"$multiply\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("multiply(a, b)")).isEqualTo("{ \"$multiply\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodePow() { - assertThat(transform("pow(a, 2)")).isEqualTo(Document.parse("{ \"$pow\" : [ \"$a\" , 2]}")); + assertThat(transform("pow(a, 2)")).isEqualTo("{ \"$pow\" : [ \"$a\" , 2]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceSqrt() { - assertThat(transform("sqrt(2)")).isEqualTo(Document.parse("{ \"$sqrt\" : 2}")); + assertThat(transform("sqrt(2)")).isEqualTo("{ \"$sqrt\" : 2}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSubtract() { - assertThat(transform("subtract(a, b)")).isEqualTo(Document.parse("{ \"$subtract\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("subtract(a, b)")).isEqualTo("{ \"$subtract\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceTrunc() { - assertThat(transform("trunc(2.1)")).isEqualTo(Document.parse("{ \"$trunc\" : 2.1}")); + assertThat(transform("trunc(2.1)")).isEqualTo("{ \"$trunc\" : 2.1}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeConcat() { - assertThat(transform("concat(a, b, 'c')")).isEqualTo(Document.parse("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}")); + assertThat(transform("concat(a, b, 'c')")).isEqualTo("{ \"$concat\" : [ \"$a\" , \"$b\" , \"c\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSubstrc() { - assertThat(transform("substr(a, 0, 1)")).isEqualTo(Document.parse("{ \"$substr\" : [ \"$a\" , 0 , 1]}")); + assertThat(transform("substr(a, 0, 1)")).isEqualTo("{ \"$substr\" : [ \"$a\" , 0 , 1]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceToLower() { - assertThat(transform("toLower(a)")).isEqualTo(Document.parse("{ \"$toLower\" : \"$a\"}")); + assertThat(transform("toLower(a)")).isEqualTo("{ \"$toLower\" : \"$a\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceToUpper() { - assertThat(transform("toUpper(a)")).isEqualTo(Document.parse("{ \"$toUpper\" : \"$a\"}")); + assertThat(transform("toUpper(a)")).isEqualTo("{ \"$toUpper\" : \"$a\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeStrCaseCmp() { - assertThat(transform("strcasecmp(a, b)")).isEqualTo(Document.parse("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("strcasecmp(a, b)")).isEqualTo("{ \"$strcasecmp\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceMeta() { - assertThat(transform("meta('textScore')")).isEqualTo(Document.parse("{ \"$meta\" : \"textScore\"}")); + assertThat(transform("meta('textScore')")).isEqualTo("{ \"$meta\" : \"textScore\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeArrayElemAt() { - assertThat(transform("arrayElemAt(a, 10)")).isEqualTo(Document.parse("{ \"$arrayElemAt\" : [ \"$a\" , 10]}")); + assertThat(transform("arrayElemAt(a, 10)")).isEqualTo("{ \"$arrayElemAt\" : [ \"$a\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeConcatArrays() { assertThat(transform("concatArrays(a, b, c)")) - .isEqualTo(Document.parse("{ \"$concatArrays\" : [ \"$a\" , \"$b\" , \"$c\"]}")); + .isEqualTo("{ \"$concatArrays\" : [ \"$a\" , \"$b\" , \"$c\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeFilter() { - assertThat(transform("filter(a, 'num', '$$num' > 10)")).isEqualTo(Document.parse( - "{ \"$filter\" : { \"input\" : \"$a\" , \"as\" : \"num\" , \"cond\" : { \"$gt\" : [ \"$$num\" , 10]}}}")); + assertThat(transform("filter(a, 'num', '$$num' > 10)")).isEqualTo( + "{ \"$filter\" : { \"input\" : \"$a\" , \"as\" : \"num\" , \"cond\" : { \"$gt\" : [ \"$$num\" , 10]}}}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceIsArray() { - assertThat(transform("isArray(a)")).isEqualTo(Document.parse("{ \"$isArray\" : \"$a\"}")); + assertThat(transform("isArray(a)")).isEqualTo("{ \"$isArray\" : \"$a\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceIsSize() { - assertThat(transform("size(a)")).isEqualTo(Document.parse("{ \"$size\" : \"$a\"}")); + assertThat(transform("size(a)")).isEqualTo("{ \"$size\" : \"$a\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSlice() { - assertThat(transform("slice(a, 10)")).isEqualTo(Document.parse("{ \"$slice\" : [ \"$a\" , 10]}")); + assertThat(transform("slice(a, 10)")).isEqualTo("{ \"$slice\" : [ \"$a\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeMap() { - assertThat(transform("map(quizzes, 'grade', '$$grade' + 2)")).isEqualTo(Document.parse( - "{ \"$map\" : { \"input\" : \"$quizzes\" , \"as\" : \"grade\" , \"in\" : { \"$add\" : [ \"$$grade\" , 2]}}}")); + assertThat(transform("map(quizzes, 'grade', '$$grade' + 2)")).isEqualTo( + "{ \"$map\" : { \"input\" : \"$quizzes\" , \"as\" : \"grade\" , \"in\" : { \"$add\" : [ \"$$grade\" , 2]}}}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeLet() { - assertThat(transform("let({low:1, high:'$$low'}, gt('$$low', '$$high'))")).isEqualTo(Document.parse( - "{ \"$let\" : { \"vars\" : { \"low\" : 1 , \"high\" : \"$$low\"} , \"in\" : { \"$gt\" : [ \"$$low\" , \"$$high\"]}}}")); + assertThat(transform("let({low:1, high:'$$low'}, gt('$$low', '$$high'))")).isEqualTo( + "{ \"$let\" : { \"vars\" : { \"low\" : 1 , \"high\" : \"$$low\"} , \"in\" : { \"$gt\" : [ \"$$low\" , \"$$high\"]}}}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLiteral() { - assertThat(transform("literal($1)")).isEqualTo(Document.parse("{ \"$literal\" : \"$1\"}")); + assertThat(transform("literal($1)")).isEqualTo("{ \"$literal\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceDayOfYear() { - assertThat(transform("dayOfYear($1)")).isEqualTo(Document.parse("{ \"$dayOfYear\" : \"$1\"}")); + assertThat(transform("dayOfYear($1)")).isEqualTo("{ \"$dayOfYear\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceDayOfMonth() { - assertThat(transform("dayOfMonth($1)")).isEqualTo(Document.parse("{ \"$dayOfMonth\" : \"$1\"}")); + assertThat(transform("dayOfMonth($1)")).isEqualTo("{ \"$dayOfMonth\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceDayOfWeek() { - assertThat(transform("dayOfWeek($1)")).isEqualTo(Document.parse("{ \"$dayOfWeek\" : \"$1\"}")); + assertThat(transform("dayOfWeek($1)")).isEqualTo("{ \"$dayOfWeek\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceYear() { - assertThat(transform("year($1)")).isEqualTo(Document.parse("{ \"$year\" : \"$1\"}")); + assertThat(transform("year($1)")).isEqualTo("{ \"$year\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceMonth() { - assertThat(transform("month($1)")).isEqualTo(Document.parse("{ \"$month\" : \"$1\"}")); + assertThat(transform("month($1)")).isEqualTo("{ \"$month\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceWeek() { - assertThat(transform("week($1)")).isEqualTo(Document.parse("{ \"$week\" : \"$1\"}")); + assertThat(transform("week($1)")).isEqualTo("{ \"$week\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceHour() { - assertThat(transform("hour($1)")).isEqualTo(Document.parse("{ \"$hour\" : \"$1\"}")); + assertThat(transform("hour($1)")).isEqualTo("{ \"$hour\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceMinute() { - assertThat(transform("minute($1)")).isEqualTo(Document.parse("{ \"$minute\" : \"$1\"}")); + assertThat(transform("minute($1)")).isEqualTo("{ \"$minute\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceSecond() { - assertThat(transform("second($1)")).isEqualTo(Document.parse("{ \"$second\" : \"$1\"}")); + assertThat(transform("second($1)")).isEqualTo("{ \"$second\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceMillisecond() { - assertThat(transform("millisecond($1)")).isEqualTo(Document.parse("{ \"$millisecond\" : \"$1\"}")); + assertThat(transform("millisecond($1)")).isEqualTo("{ \"$millisecond\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceDateToString() { assertThat(transform("dateToString('%Y-%m-%d', $date)")) - .isEqualTo(Document.parse("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}")); + .isEqualTo("{ \"$dateToString\" : { \"format\" : \"%Y-%m-%d\" , \"date\" : \"$date\"}}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceCond() { assertThat(transform("cond(qty > 250, 30, 20)")).isEqualTo( - Document.parse("{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}")); + "{ \"$cond\" : { \"if\" : { \"$gt\" : [ \"$qty\" , 250]} , \"then\" : 30 , \"else\" : 20}}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeIfNull() { - assertThat(transform("ifNull(a, 10)")).isEqualTo(Document.parse("{ \"$ifNull\" : [ \"$a\" , 10]}")); + assertThat(transform("ifNull(a, 10)")).isEqualTo("{ \"$ifNull\" : [ \"$a\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeSum() { - assertThat(transform("sum(a, b)")).isEqualTo(Document.parse("{ \"$sum\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("sum(a, b)")).isEqualTo("{ \"$sum\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeAvg() { - assertThat(transform("avg(a, b)")).isEqualTo(Document.parse("{ \"$avg\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("avg(a, b)")).isEqualTo("{ \"$avg\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceFirst() { - assertThat(transform("first($1)")).isEqualTo(Document.parse("{ \"$first\" : \"$1\"}")); + assertThat(transform("first($1)")).isEqualTo("{ \"$first\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceLast() { - assertThat(transform("last($1)")).isEqualTo(Document.parse("{ \"$last\" : \"$1\"}")); + assertThat(transform("last($1)")).isEqualTo("{ \"$last\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeMax() { - assertThat(transform("max(a, b)")).isEqualTo(Document.parse("{ \"$max\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("max(a, b)")).isEqualTo("{ \"$max\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeMin() { - assertThat(transform("min(a, b)")).isEqualTo(Document.parse("{ \"$min\" : [ \"$a\" , \"$b\"]}")); + assertThat(transform("min(a, b)")).isEqualTo("{ \"$min\" : [ \"$a\" , \"$b\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodePush() { assertThat(transform("push({'item':'$item', 'quantity':'$qty'})")) - .isEqualTo(Document.parse("{ \"$push\" : { \"item\" : \"$item\" , \"quantity\" : \"$qty\"}}")); + .isEqualTo("{ \"$push\" : { \"item\" : \"$item\" , \"quantity\" : \"$qty\"}}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceAddToSet() { - assertThat(transform("addToSet($1)")).isEqualTo(Document.parse("{ \"$addToSet\" : \"$1\"}")); + assertThat(transform("addToSet($1)")).isEqualTo("{ \"$addToSet\" : \"$1\"}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeStdDevPop() { assertThat(transform("stdDevPop(scores.score)")) - .isEqualTo(Document.parse("{ \"$stdDevPop\" : [ \"$scores.score\"]}")); + .isEqualTo("{ \"$stdDevPop\" : [ \"$scores.score\"]}"); } @Test // DATAMONGO-1530 void shouldRenderMethodReferenceNodeStdDevSamp() { - assertThat(transform("stdDevSamp(age)")).isEqualTo(Document.parse("{ \"$stdDevSamp\" : [ \"$age\"]}")); + assertThat(transform("stdDevSamp(age)")).isEqualTo("{ \"$stdDevSamp\" : [ \"$age\"]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeEq() { - assertThat(transform("foo == 10")).isEqualTo(Document.parse("{ \"$eq\" : [ \"$foo\" , 10]}")); + assertThat(transform("foo == 10")).isEqualTo("{ \"$eq\" : [ \"$foo\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeNe() { - assertThat(transform("foo != 10")).isEqualTo(Document.parse("{ \"$ne\" : [ \"$foo\" , 10]}")); + assertThat(transform("foo != 10")).isEqualTo("{ \"$ne\" : [ \"$foo\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeGt() { - assertThat(transform("foo > 10")).isEqualTo(Document.parse("{ \"$gt\" : [ \"$foo\" , 10]}")); + assertThat(transform("foo > 10")).isEqualTo("{ \"$gt\" : [ \"$foo\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeGte() { - assertThat(transform("foo >= 10")).isEqualTo(Document.parse("{ \"$gte\" : [ \"$foo\" , 10]}")); + assertThat(transform("foo >= 10")).isEqualTo("{ \"$gte\" : [ \"$foo\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeLt() { - assertThat(transform("foo < 10")).isEqualTo(Document.parse("{ \"$lt\" : [ \"$foo\" , 10]}")); + assertThat(transform("foo < 10")).isEqualTo("{ \"$lt\" : [ \"$foo\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeLte() { - assertThat(transform("foo <= 10")).isEqualTo(Document.parse("{ \"$lte\" : [ \"$foo\" , 10]}")); + assertThat(transform("foo <= 10")).isEqualTo("{ \"$lte\" : [ \"$foo\" , 10]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodePow() { - assertThat(transform("foo^2")).isEqualTo(Document.parse("{ \"$pow\" : [ \"$foo\" , 2]}")); + assertThat(transform("foo^2")).isEqualTo("{ \"$pow\" : [ \"$foo\" , 2]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeOr() { - assertThat(transform("true || false")).isEqualTo(Document.parse("{ \"$or\" : [ true , false]}")); + assertThat(transform("true || false")).isEqualTo("{ \"$or\" : [ true , false]}"); } @Test // DATAMONGO-1530 void shouldRenderComplexOperationNodeOr() { assertThat(transform("1+2 || concat(a, b) || true")).isEqualTo( - Document.parse("{ \"$or\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); + "{ \"$or\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}"); } @Test // DATAMONGO-1530 void shouldRenderOperationNodeAnd() { - assertThat(transform("true && false")).isEqualTo(Document.parse("{ \"$and\" : [ true , false]}")); + assertThat(transform("true && false")).isEqualTo("{ \"$and\" : [ true , false]}"); } @Test // DATAMONGO-1530 void shouldRenderComplexOperationNodeAnd() { assertThat(transform("1+2 && concat(a, b) && true")).isEqualTo( - Document.parse("{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}")); + "{ \"$and\" : [ { \"$add\" : [ 1 , 2]} , { \"$concat\" : [ \"$a\" , \"$b\"]} , true]}"); } @Test // DATAMONGO-1530 void shouldRenderNotCorrectly() { - assertThat(transform("!true")).isEqualTo(Document.parse("{ \"$not\" : [ true]}")); + assertThat(transform("!true")).isEqualTo("{ \"$not\" : [ true]}"); } @Test // DATAMONGO-1530 void shouldRenderComplexNotCorrectly() { - assertThat(transform("!(foo > 10)")).isEqualTo(Document.parse("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}")); + assertThat(transform("!(foo > 10)")).isEqualTo("{ \"$not\" : [ { \"$gt\" : [ \"$foo\" , 10]}]}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceIndexOfBytes() { assertThat(transform("indexOfBytes(item, 'foo')")) - .isEqualTo(Document.parse("{ \"$indexOfBytes\" : [ \"$item\" , \"foo\"]}")); + .isEqualTo("{ \"$indexOfBytes\" : [ \"$item\" , \"foo\"]}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceIndexOfCP() { assertThat(transform("indexOfCP(item, 'foo')")) - .isEqualTo(Document.parse("{ \"$indexOfCP\" : [ \"$item\" , \"foo\"]}")); + .isEqualTo("{ \"$indexOfCP\" : [ \"$item\" , \"foo\"]}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceSplit() { - assertThat(transform("split(item, ',')")).isEqualTo(Document.parse("{ \"$split\" : [ \"$item\" , \",\"]}")); + assertThat(transform("split(item, ',')")).isEqualTo("{ \"$split\" : [ \"$item\" , \",\"]}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceStrLenBytes() { - assertThat(transform("strLenBytes(item)")).isEqualTo(Document.parse("{ \"$strLenBytes\" : \"$item\"}")); + assertThat(transform("strLenBytes(item)")).isEqualTo("{ \"$strLenBytes\" : \"$item\"}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceStrLenCP() { - assertThat(transform("strLenCP(item)")).isEqualTo(Document.parse("{ \"$strLenCP\" : \"$item\"}")); + assertThat(transform("strLenCP(item)")).isEqualTo("{ \"$strLenCP\" : \"$item\"}"); } @Test // DATAMONGO-1548 void shouldRenderMethodSubstrCP() { - assertThat(transform("substrCP(item, 0, 5)")).isEqualTo(Document.parse("{ \"$substrCP\" : [ \"$item\" , 0 , 5]}")); + assertThat(transform("substrCP(item, 0, 5)")).isEqualTo("{ \"$substrCP\" : [ \"$item\" , 0 , 5]}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceReverseArray() { - assertThat(transform("reverseArray(array)")).isEqualTo(Document.parse("{ \"$reverseArray\" : \"$array\"}")); + assertThat(transform("reverseArray(array)")).isEqualTo("{ \"$reverseArray\" : \"$array\"}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceReduce() { - assertThat(transform("reduce(field, '', {'$concat':{'$$value','$$this'}})")).isEqualTo(Document.parse( - "{ \"$reduce\" : { \"input\" : \"$field\" , \"initialValue\" : \"\" , \"in\" : { \"$concat\" : [ \"$$value\" , \"$$this\"]}}}")); + assertThat(transform("reduce(field, '', {'$concat':{'$$value','$$this'}})")).isEqualTo( + "{ \"$reduce\" : { \"input\" : \"$field\" , \"initialValue\" : \"\" , \"in\" : { \"$concat\" : [ \"$$value\" , \"$$this\"]}}}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceZip() { assertThat(transform("zip(new String[]{'$array1', '$array2'})")) - .isEqualTo(Document.parse("{ \"$zip\" : { \"inputs\" : [ \"$array1\" , \"$array2\"]}}")); + .isEqualTo("{ \"$zip\" : { \"inputs\" : [ \"$array1\" , \"$array2\"]}}"); } @Test // DATAMONGO-1548 void shouldRenderMethodReferenceZipWithOptionalArgs() { - assertThat(transform("zip(new String[]{'$array1', '$array2'}, true, new int[]{1,2})")).isEqualTo(Document.parse( - "{ \"$zip\" : { \"inputs\" : [ \"$array1\" , \"$array2\"] , \"useLongestLength\" : true , \"defaults\" : [ 1 , 2]}}")); + assertThat(transform("zip(new String[]{'$array1', '$array2'}, true, new int[]{1,2})")).isEqualTo( + "{ \"$zip\" : { \"inputs\" : [ \"$array1\" , \"$array2\"] , \"useLongestLength\" : true , \"defaults\" : [ 1 , 2]}}"); } @Test // DATAMONGO-1548 void shouldRenderMethodIn() { - assertThat(transform("in('item', array)")).isEqualTo(Document.parse("{ \"$in\" : [ \"item\" , \"$array\"]}")); + assertThat(transform("in('item', array)")).isEqualTo("{ \"$in\" : [ \"item\" , \"$array\"]}"); } @Test // DATAMONGO-1548 void shouldRenderMethodRefereneIsoDayOfWeek() { - assertThat(transform("isoDayOfWeek(date)")).isEqualTo(Document.parse("{ \"$isoDayOfWeek\" : \"$date\"}")); + assertThat(transform("isoDayOfWeek(date)")).isEqualTo("{ \"$isoDayOfWeek\" : \"$date\"}"); } @Test // DATAMONGO-1548 void shouldRenderMethodRefereneIsoWeek() { - assertThat(transform("isoWeek(date)")).isEqualTo(Document.parse("{ \"$isoWeek\" : \"$date\"}")); + assertThat(transform("isoWeek(date)")).isEqualTo("{ \"$isoWeek\" : \"$date\"}"); } @Test // DATAMONGO-1548 void shouldRenderMethodRefereneIsoWeekYear() { - assertThat(transform("isoWeekYear(date)")).isEqualTo(Document.parse("{ \"$isoWeekYear\" : \"$date\"}")); + assertThat(transform("isoWeekYear(date)")).isEqualTo("{ \"$isoWeekYear\" : \"$date\"}"); } @Test // DATAMONGO-1548 void shouldRenderMethodRefereneType() { - assertThat(transform("type(a)")).isEqualTo(Document.parse("{ \"$type\" : \"$a\"}")); + assertThat(transform("type(a)")).isEqualTo("{ \"$type\" : \"$a\"}"); } @Test // DATAMONGO-2077 void shouldRenderArrayToObjectWithFieldReference() { - assertThat(transform("arrayToObject(field)")).isEqualTo(Document.parse("{ \"$arrayToObject\" : \"$field\"}")); + assertThat(transform("arrayToObject(field)")).isEqualTo("{ \"$arrayToObject\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderArrayToObjectWithArray() { assertThat(transform("arrayToObject(new String[]{'key', 'value'})")) - .isEqualTo(Document.parse("{ \"$arrayToObject\" : [\"key\", \"value\"]}")); + .isEqualTo("{ \"$arrayToObject\" : [\"key\", \"value\"]}"); } @Test // DATAMONGO-2077 void shouldRenderObjectToArrayWithFieldReference() { - assertThat(transform("objectToArray(field)")).isEqualTo(Document.parse("{ \"$objectToArray\" : \"$field\"}")); + assertThat(transform("objectToArray(field)")).isEqualTo("{ \"$objectToArray\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderMergeObjects() { assertThat(transform("mergeObjects(field1, $$ROOT)")) - .isEqualTo(Document.parse("{ \"$mergeObjects\" : [\"$field1\", \"$$ROOT\"]}")); + .isEqualTo("{ \"$mergeObjects\" : [\"$field1\", \"$$ROOT\"]}"); } @Test // DATAMONGO-2077 void shouldRenderTrimWithoutChars() { - assertThat(transform("trim(field)")).isEqualTo(Document.parse("{ \"$trim\" : {\"input\" : \"$field\"}}")); + assertThat(transform("trim(field)")).isEqualTo("{ \"$trim\" : {\"input\" : \"$field\"}}"); } @Test // DATAMONGO-2077 void shouldRenderTrimWithChars() { assertThat(transform("trim(field, 'ie')")) - .isEqualTo(Document.parse("{ \"$trim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")); + .isEqualTo("{ \"$trim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}"); } @Test // DATAMONGO-2077 void shouldRenderTrimWithCharsFromFieldReference() { assertThat(transform("trim(field1, field2)")) - .isEqualTo(Document.parse("{ \"$trim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")); + .isEqualTo("{ \"$trim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}"); } @Test // DATAMONGO-2077 void shouldRenderLtrimWithoutChars() { - assertThat(transform("ltrim(field)")).isEqualTo(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field\"}}")); + assertThat(transform("ltrim(field)")).isEqualTo("{ \"$ltrim\" : {\"input\" : \"$field\"}}"); } @Test // DATAMONGO-2077 void shouldRenderLtrimWithChars() { assertThat(transform("ltrim(field, 'ie')")) - .isEqualTo(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")); + .isEqualTo("{ \"$ltrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}"); } @Test // DATAMONGO-2077 void shouldRenderLtrimWithCharsFromFieldReference() { assertThat(transform("ltrim(field1, field2)")) - .isEqualTo(Document.parse("{ \"$ltrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")); + .isEqualTo("{ \"$ltrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}"); } @Test // DATAMONGO-2077 void shouldRenderRtrimWithoutChars() { - assertThat(transform("rtrim(field)")).isEqualTo(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field\"}}")); + assertThat(transform("rtrim(field)")).isEqualTo("{ \"$rtrim\" : {\"input\" : \"$field\"}}"); } @Test // DATAMONGO-2077 void shouldRenderRtrimWithChars() { assertThat(transform("rtrim(field, 'ie')")) - .isEqualTo(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}")); + .isEqualTo("{ \"$rtrim\" : {\"input\" : \"$field\", \"chars\" : \"ie\" }}"); } @Test // DATAMONGO-2077 void shouldRenderRtrimWithCharsFromFieldReference() { assertThat(transform("rtrim(field1, field2)")) - .isEqualTo(Document.parse("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}")); + .isEqualTo("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}"); } @Test // DATAMONGO-2077 void shouldRenderConvertWithoutOptionalParameters() { assertThat(transform("convert(field, 'string')")) - .isEqualTo(Document.parse("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"string\" }}")); + .isEqualTo("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"string\" }}"); } @Test // DATAMONGO-2077 void shouldRenderConvertWithOnError() { - assertThat(transform("convert(field, 'int', 'Not an integer.')")).isEqualTo(Document - .parse("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\" }}")); + assertThat(transform("convert(field, 'int', 'Not an integer.')")) + .isEqualTo("{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\" }}"); } @Test // DATAMONGO-2077 void shouldRenderConvertWithOnErrorOnNull() { - assertThat(transform("convert(field, 'int', 'Not an integer.', -1)")).isEqualTo(Document.parse( - "{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\", \"onNull\" : -1 }}")); + assertThat(transform("convert(field, 'int', 'Not an integer.', -1)")).isEqualTo( + "{ \"$convert\" : {\"input\" : \"$field\", \"to\" : \"int\", \"onError\" : \"Not an integer.\", \"onNull\" : -1 }}"); } @Test // DATAMONGO-2077 void shouldRenderToBool() { - assertThat(transform("toBool(field)")).isEqualTo(Document.parse("{ \"$toBool\" : \"$field\"}")); + assertThat(transform("toBool(field)")).isEqualTo("{ \"$toBool\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToDate() { - assertThat(transform("toDate(field)")).isEqualTo(Document.parse("{ \"$toDate\" : \"$field\"}")); + assertThat(transform("toDate(field)")).isEqualTo("{ \"$toDate\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToDecimal() { - assertThat(transform("toDecimal(field)")).isEqualTo(Document.parse("{ \"$toDecimal\" : \"$field\"}")); + assertThat(transform("toDecimal(field)")).isEqualTo("{ \"$toDecimal\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToDouble() { - assertThat(transform("toDouble(field)")).isEqualTo(Document.parse("{ \"$toDouble\" : \"$field\"}")); + assertThat(transform("toDouble(field)")).isEqualTo("{ \"$toDouble\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToInt() { - assertThat(transform("toInt(field)")).isEqualTo(Document.parse("{ \"$toInt\" : \"$field\"}")); + assertThat(transform("toInt(field)")).isEqualTo("{ \"$toInt\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToLong() { - assertThat(transform("toLong(field)")).isEqualTo(Document.parse("{ \"$toLong\" : \"$field\"}")); + assertThat(transform("toLong(field)")).isEqualTo("{ \"$toLong\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToObjectId() { - assertThat(transform("toObjectId(field)")).isEqualTo(Document.parse("{ \"$toObjectId\" : \"$field\"}")); + assertThat(transform("toObjectId(field)")).isEqualTo("{ \"$toObjectId\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderToString() { - assertThat(transform("toString(field)")).isEqualTo(Document.parse("{ \"$toString\" : \"$field\"}")); + assertThat(transform("toString(field)")).isEqualTo("{ \"$toString\" : \"$field\"}"); } @Test // DATAMONGO-2077 void shouldRenderDateFromStringWithoutOptionalParameters() { assertThat(transform("dateFromString(field)")) - .isEqualTo(Document.parse("{ \"$dateFromString\" : {\"dateString\" : \"$field\" }}")); + .isEqualTo("{ \"$dateFromString\" : {\"dateString\" : \"$field\" }}"); } @Test // DATAMONGO-2077 void shouldRenderDateFromStringWithFormat() { assertThat(transform("dateFromString(field, 'DD-MM-YYYY')")).isEqualTo( - Document.parse("{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\" }}")); + "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\" }}"); } @Test // DATAMONGO-2077 void shouldRenderDateFromStringWithFormatAndTimezone() { - assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC')")).isEqualTo(Document.parse( - "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\" }}")); + assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC')")).isEqualTo( + "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\" }}"); } @Test // DATAMONGO-2077 void shouldRenderDateFromStringWithFormatTimezoneAndOnError() { - assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1)")).isEqualTo(Document.parse( - "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1 }}")); + assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1)")).isEqualTo( + "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1 }}"); } @Test // DATAMONGO-2077 void shouldRenderDateFromStringWithFormatTimezoneOnErrorAndOnNull() { - assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1, -2)")).isEqualTo(Document.parse( - "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1, \"onNull\" : -2}}")); + assertThat(transform("dateFromString(field, 'DD-MM-YYYY', 'UTC', -1, -2)")).isEqualTo( + "{ \"$dateFromString\" : {\"dateString\" : \"$field\", \"format\" : \"DD-MM-YYYY\", \"timezone\" : \"UTC\", \"onError\" : -1, \"onNull\" : -2}}"); } @Test // DATAMONGO-2077, DATAMONGO-2671 void shouldRenderDateFromParts() { - assertThat(transform("dateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo(Document.parse( - "{ \"$dateFromParts\" : {\"year\" : \"$y\", \"month\" : \"$m\", \"day\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}")); + assertThat(transform("dateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo( + "{ \"$dateFromParts\" : {\"year\" : \"$y\", \"month\" : \"$m\", \"day\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}"); } @Test // DATAMONGO-2077, DATAMONGO-2671 void shouldRenderIsoDateFromParts() { - assertThat(transform("isoDateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo(Document.parse( - "{ \"$dateFromParts\" : {\"isoWeekYear\" : \"$y\", \"isoWeek\" : \"$m\", \"isoDayOfWeek\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}")); + assertThat(transform("isoDateFromParts(y, m, d, h, mm, s, ms, 'UTC')")).isEqualTo( + "{ \"$dateFromParts\" : {\"isoWeekYear\" : \"$y\", \"isoWeek\" : \"$m\", \"isoDayOfWeek\" : \"$d\", \"hour\" : \"$h\", \"minute\" : \"$mm\", \"second\" : \"$s\", \"millisecond\" : \"$ms\", \"timezone\" : \"UTC\"}}"); } @Test // DATAMONGO-2077 void shouldRenderDateToParts() { assertThat(transform("dateToParts(field, 'UTC', false)")).isEqualTo( - Document.parse("{ \"$dateToParts\" : {\"date\" : \"$field\", \"timezone\" : \"UTC\", \"iso8601\" : false}}")); + "{ \"$dateToParts\" : {\"date\" : \"$field\", \"timezone\" : \"UTC\", \"iso8601\" : false}}"); } @Test // DATAMONGO-2077 void shouldRenderIndexOfArray() { assertThat(transform("indexOfArray(field, 2)")) - .isEqualTo(Document.parse("{ \"$indexOfArray\" : [\"$field\", 2 ]}")); + .isEqualTo("{ \"$indexOfArray\" : [\"$field\", 2 ]}"); } @Test // DATAMONGO-2077 void shouldRenderRange() { - assertThat(transform("range(0, 10, 2)")).isEqualTo(Document.parse("{ \"$range\" : [0, 10, 2 ]}")); + assertThat(transform("range(0, 10, 2)")).isEqualTo("{ \"$range\" : [0, 10, 2 ]}"); } @Test // DATAMONGO-2370 void shouldRenderRound() { - assertThat(transform("round(field)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\"]}")); + assertThat(transform("round(field)")).isEqualTo("{ \"$round\" : [\"$field\"]}"); } @Test // DATAMONGO-2370 void shouldRenderRoundWithPlace() { - assertThat(transform("round(field, 2)")).isEqualTo(Document.parse("{ \"$round\" : [\"$field\", 2]}")); + assertThat(transform("round(field, 2)")).isEqualTo("{ \"$round\" : [\"$field\", 2]}"); } @Test // GH-3714 void shouldRenderDegreesToRadians() { - assertThat(transform("degreesToRadians(angle_a)")).isEqualTo(Document.parse("{ \"$degreesToRadians\" : \"$angle_a\"}")); + assertThat(transform("degreesToRadians(angle_a)")).isEqualTo("{ \"$degreesToRadians\" : \"$angle_a\"}"); } @Test // GH-3712 void shouldRenderCovariancePop() { assertThat(transform("covariancePop(field1, field2)")) - .isEqualTo(Document.parse("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}")); + .isEqualTo("{ \"$covariancePop\" : [\"$field1\", \"$field2\"]}"); } @Test // GH-3712 void shouldRenderCovarianceSamp() { assertThat(transform("covarianceSamp(field1, field2)")) - .isEqualTo(Document.parse("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}")); + .isEqualTo("{ \"$covarianceSamp\" : [\"$field1\", \"$field2\"]}"); } @Test // GH-3715 void shouldRenderRank() { - assertThat(transform("rank()")).isEqualTo(Document.parse("{ $rank : {} }")); + assertThat(transform("rank()")).isEqualTo("{ $rank : {} }"); } @Test // GH-3715 void shouldRenderDenseRank() { - assertThat(transform("denseRank()")).isEqualTo(Document.parse("{ $denseRank : {} }")); + assertThat(transform("denseRank()")).isEqualTo("{ $denseRank : {} }"); } @Test // GH-3717 void shouldRenderDocumentNumber() { - assertThat(transform("documentNumber()")).isEqualTo(Document.parse("{ $documentNumber : {} }")); + assertThat(transform("documentNumber()")).isEqualTo("{ $documentNumber : {} }"); } @Test // GH-3727 void rendersShift() { assertThat(transform("shift(quantity, 1)")) - .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1 } }")); + .isEqualTo("{ $shift: { output: \"$quantity\", by: 1 } }"); } @Test // GH-3727 void rendersShiftWithDefault() { assertThat(transform("shift(quantity, 1, 'Not available')")) - .isEqualTo(Document.parse("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }")); + .isEqualTo("{ $shift: { output: \"$quantity\", by: 1, default: \"Not available\" } }"); } @Test // GH-3716 void shouldRenderDerivative() { assertThat(transform("derivative(miles, 'hour')")) - .isEqualTo(Document.parse("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }")); + .isEqualTo("{ \"$derivative\" : { input : '$miles', unit : 'hour'} }"); } @Test // GH-3721 void shouldRenderIntegral() { - assertThat(transform("integral(field)")).isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\" }}")); + assertThat(transform("integral(field)")).isEqualTo("{ \"$integral\" : { \"input\" : \"$field\" }}"); } @Test // GH-3721 void shouldRenderIntegralWithUnit() { assertThat(transform("integral(field, 'hour')")) - .isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}")); + .isEqualTo("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}"); } @Test // GH-3728 void shouldRenderSin() { - assertThat(transform("sin(angle)")).isEqualTo(Document.parse("{ \"$sin\" : \"$angle\"}")); + assertThat(transform("sin(angle)")).isEqualTo("{ \"$sin\" : \"$angle\"}"); } @Test // GH-3728 void shouldRenderSinh() { - assertThat(transform("sinh(angle)")).isEqualTo(Document.parse("{ \"$sinh\" : \"$angle\"}")); + assertThat(transform("sinh(angle)")).isEqualTo("{ \"$sinh\" : \"$angle\"}"); } @Test // GH-3710 void shouldRenderCos() { - assertThat(transform("cos(angle)")).isEqualTo(Document.parse("{ \"$cos\" : \"$angle\"}")); + assertThat(transform("cos(angle)")).isEqualTo("{ \"$cos\" : \"$angle\"}"); } @Test // GH-3710 void shouldRenderCosh() { - assertThat(transform("cosh(angle)")).isEqualTo(Document.parse("{ \"$cosh\" : \"$angle\"}")); + assertThat(transform("cosh(angle)")).isEqualTo("{ \"$cosh\" : \"$angle\"}"); } @Test // GH-3730 void shouldRenderTan() { - assertThat(transform("tan(angle)")).isEqualTo(Document.parse("{ \"$tan\" : \"$angle\"}")); + assertThat(transform("tan(angle)")).isEqualTo("{ \"$tan\" : \"$angle\"}"); } @Test // GH-3730 void shouldRenderTanh() { - assertThat(transform("tanh(angle)")).isEqualTo(Document.parse("{ \"$tanh\" : \"$angle\"}")); + assertThat(transform("tanh(angle)")).isEqualTo("{ \"$tanh\" : \"$angle\"}"); } - private Object transform(String expression, Object... params) { + private Document transform(String expression, Object... params) { + return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); + } + + private Object transformValue(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); } diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index 9b00811a7b..6373eb663c 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -85,7 +85,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (+++*+++ via `plus`), `ceil`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `trunc` +| `abs`, `add` (+++*+++ via `plus`), `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` @@ -112,7 +112,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `type` | Convert Aggregation Operators -| `convert`, `toBool`, `toDate`, `toDecimal`, `toDouble`, `toInt`, `toLong`, `toObjectId`, `toString` +| `convert`, `degreesToRadians`, `toBool`, `toDate`, `toDecimal`, `toDouble`, `toInt`, `toLong`, `toObjectId`, `toString` | Object Aggregation Operators | `objectToArray`, `mergeObjects` From aca403c11240a5e2253d36e4ecba627283dd9ee7 Mon Sep 17 00:00:00 2001 From: Ryan Gibb Date: Fri, 30 Jul 2021 14:06:42 +0100 Subject: [PATCH 0506/1381] Fix a typo in `MongoConverter` javadoc. Original pull request: #3758. --- .../data/mongodb/core/convert/MongoConverter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index 8887a3bd03..20499d3173 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -40,13 +40,14 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author Ryan Gibb */ public interface MongoConverter extends EntityConverter, MongoPersistentProperty, Object, Bson>, MongoWriter, EntityReader { /** - * Returns thw {@link TypeMapper} being used to write type information into {@link Document}s created with that + * Returns the {@link TypeMapper} being used to write type information into {@link Document}s created with that * converter. * * @return will never be {@literal null}. From 869b88702db52a25417da5427859f75621d78e7d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 25 Aug 2021 10:15:13 +0200 Subject: [PATCH 0507/1381] Polishing. Fix typo in reference docs. See #3758 --- src/main/asciidoc/reference/aggregation-framework.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index 6373eb663c..f23b290697 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -88,7 +88,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `abs`, `add` (+++*+++ via `plus`), `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` | String Aggregation Operators -| `concat`, `substr`, `toLower`, `toUpper`, `stcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` +| `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` | Comparison Aggregation Operators | `eq` (+++*+++ via `is`), `gt`, `gte`, `lt`, `lte`, `ne` From afef243634e4efa215755cf14b678bebe10ff92a Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 26 Jul 2021 08:46:22 +0200 Subject: [PATCH 0508/1381] Add support for `$dateAdd` aggregation operator. Closes: #3713 Original pull request: #3748. --- .../core/aggregation/DateOperators.java | 144 +++++++++++++++++- .../core/spel/MethodReferenceNode.java | 1 + .../aggregation/DateOperatorsUnitTests.java | 44 ++++++ .../SpelExpressionTransformerUnitTests.java | 6 + 4 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index 15f10f7d6c..f7abf88d72 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.core.aggregation; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -156,7 +157,7 @@ public static Timezone none() { * representing an Olson Timezone Identifier or UTC Offset. * * @param value the plain timezone {@link String}, a {@link Field} holding the timezone or an - * {@link AggregationExpression} resulting in the timezone. + * {@link AggregationExpression} resulting in the timezone. * @return new instance of {@link Timezone}. */ public static Timezone valueOf(Object value) { @@ -274,6 +275,41 @@ public DateOperatorFactory withTimezone(Timezone timezone) { return new DateOperatorFactory(fieldReference, expression, dateValue, timezone); } + /** + * Creates new {@link AggregationExpression} that adds the value of the given {@link AggregationExpression + * expression} (in {@literal units). @param expression must not be {@literal null}. + * + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + * @since 3.3 + */ + public DateAdd addValueOf(AggregationExpression expression, String unit) { + return applyTimezone(DateAdd.addValueOf(expression, unit).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that adds the value stored at the given {@literal field} (in + * {@literal units). @param fieldReference must not be {@literal null}. + * + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + * @since 3.3 + */ + public DateAdd addValueOf(String fieldReference, String unit) { + return applyTimezone(DateAdd.addValueOf(fieldReference, unit).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that adds the given value (in {@literal units). @param value must not + * be {@literal null}. @param unit the unit of measure. Must not be {@literal null}. + * + * @return + * @since 3.3 new instance of {@link DateAdd}. + */ + public DateAdd add(Object value, String unit) { + return applyTimezone(DateAdd.addValue(value, unit).toDate(dateReference()), timezone); + } + /** * Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and * 366. @@ -1480,7 +1516,6 @@ protected java.util.Map append(String key, Object value) { } else { clone.put("timezone", ((Timezone) value).value); } - } else { clone.put(key, value); } @@ -1911,7 +1946,7 @@ default T millisecondOf(AggregationExpression expression) { * @author Matt Morrissette * @author Christoph Strobl * @see https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/ * @since 2.1 */ public static class DateFromParts extends TimezonedDateAggregationExpression implements DateParts { @@ -2086,7 +2121,7 @@ default DateFromParts yearOf(AggregationExpression expression) { * @author Matt Morrissette * @author Christoph Strobl * @see https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromParts/ * @since 2.1 */ public static class IsoDateFromParts extends TimezonedDateAggregationExpression @@ -2262,7 +2297,7 @@ default IsoDateFromParts isoWeekYearOf(AggregationExpression expression) { * @author Matt Morrissette * @author Christoph Strobl * @see https://docs.mongodb.com/manual/reference/operator/aggregation/dateToParts/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/dateToParts/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateToParts/ * @since 2.1 */ public static class DateToParts extends TimezonedDateAggregationExpression { @@ -2343,7 +2378,7 @@ protected String getMongoMethod() { * @author Matt Morrissette * @author Christoph Strobl * @see https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/ + * "https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/">https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/ * @since 2.1 */ public static class DateFromString extends TimezonedDateAggregationExpression { @@ -2418,6 +2453,103 @@ protected String getMongoMethod() { } } + /** + * {@link AggregationExpression} for {@code $dateAdd}.
      + * NOTE: Requires MongoDB 5.0 or later. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class DateAdd extends TimezonedDateAggregationExpression { + + private DateAdd(Object value) { + super(value); + } + + /** + * Add the number of {@literal units} of the result of the given {@link AggregationExpression expression} to a + * {@link #toDate(Object) start date}. + * + * @param expression must not be {@literal null}. + * @param unit must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public static DateAdd addValueOf(AggregationExpression expression, String unit) { + return addValue(expression, unit); + } + + /** + * Add the number of {@literal units} from a {@literal field} to a {@link #toDate(Object) start date}. + * + * @param fieldReference must not be {@literal null}. + * @param unit must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public static DateAdd addValueOf(String fieldReference, String unit) { + return addValue(Fields.field(fieldReference), unit); + } + + /** + * Add the number of {@literal units} to a {@link #toDate(Object) start date}. + * + * @param value must not be {@literal null}. + * @param unit must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public static DateAdd addValue(Object value, String unit) { + + Map args = new HashMap<>(); + args.put("unit", unit); + args.put("amount", value); + return new DateAdd(args); + } + + /** + * Define the start date, in UTC, for the addition operation. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public DateAdd toDateOf(AggregationExpression expression) { + return toDate(expression); + } + + /** + * Define the start date, in UTC, for the addition operation. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public DateAdd toDateOf(String fieldReference) { + return toDate(Fields.field(fieldReference)); + } + + /** + * Define the start date, in UTC, for the addition operation. + * + * @param dateExpression anything that evaluates to a valid date. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public DateAdd toDate(Object dateExpression) { + return new DateAdd(append("startDate", dateExpression)); + } + + /** + * Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used. + * + * @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead. + * @return new instance of {@link DateAdd}. + */ + public DateAdd withTimezone(Timezone timezone) { + return new DateAdd(appendTimezone(argumentMap(), timezone)); + } + + @Override + protected String getMongoMethod() { + return "$dateAdd"; + } + } + @SuppressWarnings("unchecked") private static T applyTimezone(T instance, Timezone timezone) { return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 1efe94c757..6b4daa15b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -144,6 +144,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("literal", singleArgRef().forOperator("$literal")); // DATE OPERATORS + map.put("dateAdd", mapArgRef().forOperator("$dateAdd").mappingParametersTo("startDate", "unit", "amount", "timezone")); map.put("dayOfYear", singleArgRef().forOperator("$dayOfYear")); map.put("dayOfMonth", singleArgRef().forOperator("$dayOfMonth")); map.put("dayOfWeek", singleArgRef().forOperator("$dayOfWeek")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java new file mode 100644 index 0000000000..036edfdce1 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2021. 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 + * + * https://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.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.aggregation.DateOperators.Timezone; + +/** + * @author Christoph Strobl + */ +class DateOperatorsUnitTests { + + @Test // GH-3713 + void rendersDateAdd() { + + assertThat(DateOperators.dateOf("purchaseDate").add(3, "day").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }")); + } + + @Test // GH-3713 + void rendersDateAddWithTimezone() { + + assertThat(DateOperators.dateOf("purchaseDate").withTimezone(Timezone.valueOf("America/Chicago")).add(3, "day") + .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( + "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }")); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 193ffb520d..337d61f984 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1039,6 +1039,12 @@ private Document transform(String expression, Object... params) { } private Object transformValue(String expression, Object... params) { + @Test // GH-3713 + void shouldRenderDateAdd() { + assertThat(transform("dateAdd(purchaseDate, 'day', 3)")).isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }")); + } + + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); } From fc41793d5de7bf48f551638e9836ef0eaceb1c43 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 26 Jul 2021 09:08:18 +0200 Subject: [PATCH 0509/1381] Add support for `$dateDiff` aggregation operator. Closes: #3713 Original pull request: #3748. --- .../core/aggregation/DateOperators.java | 144 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 1 + .../aggregation/DateOperatorsUnitTests.java | 16 ++ .../SpelExpressionTransformerUnitTests.java | 5 + 4 files changed, 166 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index f7abf88d72..a9b1d411cd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -340,6 +340,42 @@ public DayOfWeek dayOfWeek() { return applyTimezone(DayOfWeek.dayOfWeek(dateReference()), timezone); } + /** + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units) to the date + * computed by the given {@link AggregationExpression expression}. @param expression must not be {@literal null}. + * + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + * @since 3.3 + */ + public DateDiff diffValueOf(AggregationExpression expression, String unit) { + return applyTimezone(DateDiff.diffValueOf(expression, unit).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units) to the date stored + * at the given {@literal field}. @param expression must not be {@literal null}. + * + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + * @since 3.3 + */ + public DateDiff diffValueOf(String fieldReference, String unit) { + return applyTimezone(DateDiff.diffValueOf(fieldReference, unit).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units) to the date given + * {@literal value}. @param value anything the resolves to a valid date. Must not be {@literal null}. + * + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + * @since 3.3 + */ + public DateDiff diff(Object value, String unit) { + return applyTimezone(DateDiff.diffValue(value, unit).toDate(dateReference()), timezone); + } + /** * Creates new {@link AggregationExpression} that returns the year portion of a date. * @@ -2550,6 +2586,114 @@ protected String getMongoMethod() { } } + /** + * {@link AggregationExpression} for {@code $dateDiff}.
      + * NOTE: Requires MongoDB 5.0 or later. + * + * @author Christoph Strobl + * @since 3.3 + */ + public static class DateDiff extends TimezonedDateAggregationExpression { + + private DateDiff(Object value) { + super(value); + } + + /** + * Add the number of {@literal units} of the result of the given {@link AggregationExpression expression} to a + * {@link #toDate(Object) start date}. + * + * @param expression must not be {@literal null}. + * @param unit must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public static DateDiff diffValueOf(AggregationExpression expression, String unit) { + return diffValue(expression, unit); + } + + /** + * Add the number of {@literal units} from a {@literal field} to a {@link #toDate(Object) start date}. + * + * @param fieldReference must not be {@literal null}. + * @param unit must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public static DateDiff diffValueOf(String fieldReference, String unit) { + return diffValue(Fields.field(fieldReference), unit); + } + + /** + * Add the number of {@literal units} to a {@link #toDate(Object) start date}. + * + * @param value must not be {@literal null}. + * @param unit must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public static DateDiff diffValue(Object value, String unit) { + + Map args = new HashMap<>(); + args.put("unit", unit); + args.put("endDate", value); + return new DateDiff(args); + } + + /** + * Define the start date, in UTC, for the addition operation. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public DateDiff toDateOf(AggregationExpression expression) { + return toDate(expression); + } + + /** + * Define the start date, in UTC, for the addition operation. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public DateDiff toDateOf(String fieldReference) { + return toDate(Fields.field(fieldReference)); + } + + /** + * Define the start date, in UTC, for the addition operation. + * + * @param dateExpression anything that evaluates to a valid date. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. + */ + public DateDiff toDate(Object dateExpression) { + return new DateDiff(append("startDate", dateExpression)); + } + + /** + * Optionally set the {@link Timezone} to use. If not specified {@literal UTC} is used. + * + * @param timezone must not be {@literal null}. Consider {@link Timezone#none()} instead. + * @return new instance of {@link DateAdd}. + */ + public DateDiff withTimezone(Timezone timezone) { + return new DateDiff(appendTimezone(argumentMap(), timezone)); + } + + /** + * Set the start day of the week if the unit if measure is set to {@literal week}. Uses {@literal Sunday} by + * default. + * + * @param day must not be {@literal null}. + * @return new instance of {@link DateDiff}. + */ + public DateDiff startOfWeek(Object day) { + return new DateDiff(append("startOfWeek", day)); + } + + @Override + protected String getMongoMethod() { + return "$dateDiff"; + } + } + @SuppressWarnings("unchecked") private static T applyTimezone(T instance, Timezone timezone) { return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 6b4daa15b8..6a60a7df1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -145,6 +145,7 @@ public class MethodReferenceNode extends ExpressionNode { // DATE OPERATORS map.put("dateAdd", mapArgRef().forOperator("$dateAdd").mappingParametersTo("startDate", "unit", "amount", "timezone")); + map.put("dateDiff", mapArgRef().forOperator("$dateDiff").mappingParametersTo("startDate", "endDate", "unit","timezone", "startOfWeek")); map.put("dayOfYear", singleArgRef().forOperator("$dayOfYear")); map.put("dayOfMonth", singleArgRef().forOperator("$dayOfMonth")); map.put("dayOfWeek", singleArgRef().forOperator("$dayOfWeek")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java index 036edfdce1..ab975b852a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java @@ -40,5 +40,21 @@ void rendersDateAddWithTimezone() { .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }")); } + + @Test // GH-3713 + void rendersDateDiff() { + + assertThat( + DateOperators.dateOf("purchaseDate").diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document + .parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }")); + } + + @Test // GH-3713 + void rendersDateDiffWithTimezone() { + + assertThat(DateOperators.dateOf("purchaseDate").withTimezone(Timezone.valueOf("America/Chicago")) + .diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( + "{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\", timezone : \"America/Chicago\" } }")); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 337d61f984..33edab1d5a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1044,6 +1044,11 @@ void shouldRenderDateAdd() { assertThat(transform("dateAdd(purchaseDate, 'day', 3)")).isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }")); } + @Test // GH-3713 + void shouldRenderDateDiff() { + assertThat(transform("dateDiff(purchaseDate, delivered, 'day')")).isEqualTo(Document.parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }")); + } + private Object transform(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); From 456c1ad26abb77d82595f7e1589ca02a9a780da9 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 26 Jul 2021 09:18:16 +0200 Subject: [PATCH 0510/1381] Add shortcut for date aggregation operators working with timezone. See: #3713 Original pull request: #3748. --- .../core/aggregation/DateOperators.java | 26 +++++++++++++++++++ .../aggregation/DateOperatorsUnitTests.java | 6 ++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index a9b1d411cd..a97d64c52d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -46,6 +46,19 @@ public static DateOperatorFactory dateOf(String fieldReference) { return new DateOperatorFactory(fieldReference); } + /** + * Take the date referenced by given {@literal fieldReference}. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link DateOperatorFactory}. + * @since 3.3 + */ + public static DateOperatorFactory zonedDateOf(String fieldReference, Timezone timezone) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new DateOperatorFactory(fieldReference).withTimezone(timezone); + } + /** * Take the date resulting from the given {@link AggregationExpression}. * @@ -58,6 +71,19 @@ public static DateOperatorFactory dateOf(AggregationExpression expression) { return new DateOperatorFactory(expression); } + /** + * Take the date resulting from the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link DateOperatorFactory}. + * @since 3.3 + */ + public static DateOperatorFactory zonedDateOf(AggregationExpression expression, Timezone timezone) { + + Assert.notNull(expression, "Expression must not be null!"); + return new DateOperatorFactory(expression).withTimezone(timezone); + } + /** * Take the given value as date. *

      diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java index ab975b852a..95f977ed73 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java @@ -35,8 +35,8 @@ void rendersDateAdd() { @Test // GH-3713 void rendersDateAddWithTimezone() { - - assertThat(DateOperators.dateOf("purchaseDate").withTimezone(Timezone.valueOf("America/Chicago")).add(3, "day") + + assertThat(DateOperators.zonedDateOf("purchaseDate", Timezone.valueOf("America/Chicago")).add(3, "day") .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }")); } @@ -53,7 +53,7 @@ void rendersDateDiff() { @Test // GH-3713 void rendersDateDiffWithTimezone() { - assertThat(DateOperators.dateOf("purchaseDate").withTimezone(Timezone.valueOf("America/Chicago")) + assertThat(DateOperators.zonedDateOf("purchaseDate", Timezone.valueOf("America/Chicago")) .diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( "{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\", timezone : \"America/Chicago\" } }")); } From 24171b3ae27a4bc867fd619420543ce1b56344f5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 25 Aug 2021 10:59:26 +0200 Subject: [PATCH 0511/1381] Polishing. Introduce factory methods to convert TimeZone/ZoneId/ZoneOffset into Mongo Timezone. Introduce TemporalUnit abstraction and converters to convert ChronoUnit and TimeUnit into TemporalUnit for date operators accepting a unit parameter. See #3713 Original pull request: #3748. --- .../core/aggregation/DateOperators.java | 294 ++++++++++++++++-- .../aggregation/SetWindowFieldsOperation.java | 63 ++++ .../aggregation/DateOperatorsUnitTests.java | 48 ++- .../SpelExpressionTransformerUnitTests.java | 11 +- .../reference/aggregation-framework.adoc | 2 +- 5 files changed, 376 insertions(+), 42 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index a97d64c52d..029b994f2e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -15,10 +15,16 @@ */ package org.springframework.data.mongodb.core.aggregation; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -157,6 +163,7 @@ public static DateFromString dateFromString(String value) { * NOTE: Support for timezones in aggregations Requires MongoDB 3.6 or later. * * @author Christoph Strobl + * @author Mark Paluch * @since 2.1 */ public static class Timezone { @@ -192,6 +199,61 @@ public static Timezone valueOf(Object value) { return new Timezone(value); } + /** + * Create a {@link Timezone} for the given {@link TimeZone} rendering the offset as UTC offset. + * + * @param timeZone {@link TimeZone} rendering the offset as UTC offset. + * @return new instance of {@link Timezone}. + * @since 3.3 + */ + public static Timezone fromOffset(TimeZone timeZone) { + + Assert.notNull(timeZone, "TimeZone must not be null!"); + + return fromOffset( + ZoneOffset.ofTotalSeconds(Math.toIntExact(TimeUnit.MILLISECONDS.toSeconds(timeZone.getRawOffset())))); + } + + /** + * Create a {@link Timezone} for the given {@link ZoneOffset} rendering the offset as UTC offset. + * + * @param offset {@link ZoneOffset} rendering the offset as UTC offset. + * @return new instance of {@link Timezone}. + * @since 3.3 + */ + public static Timezone fromOffset(ZoneOffset offset) { + + Assert.notNull(offset, "ZoneOffset must not be null!"); + return new Timezone(offset.toString()); + } + + /** + * Create a {@link Timezone} for the given {@link TimeZone} rendering the offset as UTC offset. + * + * @param timeZone {@link Timezone} rendering the offset as zone identifier. + * @return new instance of {@link Timezone}. + * @since 3.3 + */ + public static Timezone fromZone(TimeZone timeZone) { + + Assert.notNull(timeZone, "TimeZone must not be null!"); + + return valueOf(timeZone.getID()); + } + + /** + * Create a {@link Timezone} for the given {@link java.time.ZoneId} rendering the offset as UTC offset. + * + * @param zoneId {@link ZoneId} rendering the offset as zone identifier. + * @return new instance of {@link Timezone}. + * @since 3.3 + */ + public static Timezone fromZone(ZoneId zoneId) { + + Assert.notNull(zoneId, "ZoneId must not be null!"); + return new Timezone(zoneId.toString()); + } + /** * Create a {@link Timezone} for the {@link Field} reference holding the Olson Timezone Identifier or UTC Offset. * @@ -212,6 +274,11 @@ public static Timezone ofField(String fieldReference) { public static Timezone ofExpression(AggregationExpression expression) { return valueOf(expression); } + + @Nullable + Object getValue() { + return value; + } } /** @@ -303,32 +370,64 @@ public DateOperatorFactory withTimezone(Timezone timezone) { /** * Creates new {@link AggregationExpression} that adds the value of the given {@link AggregationExpression - * expression} (in {@literal units). @param expression must not be {@literal null}. - * + * expression} (in {@literal units}). + * + * @param expression must not be {@literal null}. * @param unit the unit of measure. Must not be {@literal null}. - * @return new instance of {@link DateAdd}. - * @since 3.3 + * @return new instance of {@link DateAdd}. @since 3.3 */ public DateAdd addValueOf(AggregationExpression expression, String unit) { return applyTimezone(DateAdd.addValueOf(expression, unit).toDate(dateReference()), timezone); } + /** + * Creates new {@link AggregationExpression} that adds the value of the given {@link AggregationExpression + * expression} (in {@literal units}). + * + * @param expression must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. @since 3.3 + */ + public DateAdd addValueOf(AggregationExpression expression, TemporalUnit unit) { + + Assert.notNull(unit, "TemporalUnit must not be null"); + return applyTimezone(DateAdd.addValueOf(expression, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), + timezone); + } + /** * Creates new {@link AggregationExpression} that adds the value stored at the given {@literal field} (in - * {@literal units). @param fieldReference must not be {@literal null}. - * + * {@literal units}). + * + * @param fieldReference must not be {@literal null}. * @param unit the unit of measure. Must not be {@literal null}. - * @return new instance of {@link DateAdd}. - * @since 3.3 + * @return new instance of {@link DateAdd}. @since 3.3 */ public DateAdd addValueOf(String fieldReference, String unit) { return applyTimezone(DateAdd.addValueOf(fieldReference, unit).toDate(dateReference()), timezone); } /** - * Creates new {@link AggregationExpression} that adds the given value (in {@literal units). @param value must not - * be {@literal null}. @param unit the unit of measure. Must not be {@literal null}. - * + * Creates new {@link AggregationExpression} that adds the value stored at the given {@literal field} (in + * {@literal units}). + * + * @param fieldReference must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. @since 3.3 + */ + public DateAdd addValueOf(String fieldReference, TemporalUnit unit) { + + Assert.notNull(unit, "TemporalUnit must not be null"); + + return applyTimezone( + DateAdd.addValueOf(fieldReference, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that adds the given value (in {@literal units}). + * + * @param value must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. * @return * @since 3.3 new instance of {@link DateAdd}. */ @@ -336,6 +435,22 @@ public DateAdd add(Object value, String unit) { return applyTimezone(DateAdd.addValue(value, unit).toDate(dateReference()), timezone); } + /** + * Creates new {@link AggregationExpression} that adds the given value (in {@literal units}). + * + * @param value must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. + * @return + * @since 3.3 new instance of {@link DateAdd}. + */ + public DateAdd add(Object value, TemporalUnit unit) { + + Assert.notNull(unit, "TemporalUnit must not be null"); + + return applyTimezone(DateAdd.addValue(value, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), + timezone); + } + /** * Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and * 366. @@ -367,41 +482,89 @@ public DayOfWeek dayOfWeek() { } /** - * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units) to the date - * computed by the given {@link AggregationExpression expression}. @param expression must not be {@literal null}. - * + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date + * computed by the given {@link AggregationExpression expression}. + * + * @param expression must not be {@literal null}. * @param unit the unit of measure. Must not be {@literal null}. - * @return new instance of {@link DateAdd}. - * @since 3.3 + * @return new instance of {@link DateAdd}. @since 3.3 */ public DateDiff diffValueOf(AggregationExpression expression, String unit) { return applyTimezone(DateDiff.diffValueOf(expression, unit).toDate(dateReference()), timezone); } /** - * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units) to the date stored - * at the given {@literal field}. @param expression must not be {@literal null}. - * + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date + * computed by the given {@link AggregationExpression expression}. + * + * @param expression must not be {@literal null}. * @param unit the unit of measure. Must not be {@literal null}. - * @return new instance of {@link DateAdd}. - * @since 3.3 + * @return new instance of {@link DateAdd}. @since 3.3 + */ + public DateDiff diffValueOf(AggregationExpression expression, TemporalUnit unit) { + + Assert.notNull(unit, "TemporalUnit must not be null"); + + return applyTimezone( + DateDiff.diffValueOf(expression, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date stored + * at the given {@literal field}. + * + * @param fieldReference must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. @since 3.3 */ public DateDiff diffValueOf(String fieldReference, String unit) { return applyTimezone(DateDiff.diffValueOf(fieldReference, unit).toDate(dateReference()), timezone); } /** - * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units) to the date given - * {@literal value}. @param value anything the resolves to a valid date. Must not be {@literal null}. - * + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date stored + * at the given {@literal field}. + * + * @param fieldReference must not be {@literal null}. * @param unit the unit of measure. Must not be {@literal null}. - * @return new instance of {@link DateAdd}. - * @since 3.3 + * @return new instance of {@link DateAdd}. @since 3.3 + */ + public DateDiff diffValueOf(String fieldReference, TemporalUnit unit) { + + Assert.notNull(unit, "TemporalUnit must not be null"); + + return applyTimezone( + DateDiff.diffValueOf(fieldReference, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), timezone); + } + + /** + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date given + * {@literal value}. + * + * @param value anything the resolves to a valid date. Must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. @since 3.3 */ public DateDiff diff(Object value, String unit) { return applyTimezone(DateDiff.diffValue(value, unit).toDate(dateReference()), timezone); } + /** + * Creates new {@link AggregationExpression} that calculates the difference (in {@literal units}) to the date given + * {@literal value}. + * + * @param value anything the resolves to a valid date. Must not be {@literal null}. + * @param unit the unit of measure. Must not be {@literal null}. + * @return new instance of {@link DateAdd}. @since 3.3 + */ + public DateDiff diff(Object value, TemporalUnit unit) { + + Assert.notNull(unit, "TemporalUnit must not be null"); + + return applyTimezone(DateDiff.diffValue(value, unit.name().toLowerCase(Locale.ROOT)).toDate(dateReference()), + timezone); + } + /** * Creates new {@link AggregationExpression} that returns the year portion of a date. * @@ -2720,6 +2883,85 @@ protected String getMongoMethod() { } } + /** + * Interface defining a temporal unit for date operators. + * + * @author Mark Paluch + * @since 3.3 + */ + public interface TemporalUnit { + + String name(); + + /** + * Converts the given time unit into a {@link TemporalUnit}. Supported units are: days, hours, minutes, seconds, and + * milliseconds. + * + * @param timeUnit the time unit to convert, must not be {@literal null}. + * @return + * @throws IllegalArgumentException if the {@link TimeUnit} is {@literal null} or not supported for conversion. + */ + static TemporalUnit from(TimeUnit timeUnit) { + + Assert.notNull(timeUnit, "TimeUnit must not be null"); + + switch (timeUnit) { + case DAYS: + return TemporalUnits.DAY; + case HOURS: + return TemporalUnits.HOUR; + case MINUTES: + return TemporalUnits.MINUTE; + case SECONDS: + return TemporalUnits.SECOND; + case MILLISECONDS: + return TemporalUnits.MILLISECOND; + } + + throw new IllegalArgumentException(String.format("Cannot create TemporalUnit from %s", timeUnit)); + } + + /** + * Converts the given chrono unit into a {@link TemporalUnit}. Supported units are: years, weeks, months, days, + * hours, minutes, seconds, and millis. + * + * @param chronoUnit the chrono unit to convert, must not be {@literal null}. + * @return + * @throws IllegalArgumentException if the {@link TimeUnit} is {@literal null} or not supported for conversion. + */ + static TemporalUnit from(ChronoUnit chronoUnit) { + + switch (chronoUnit) { + case YEARS: + return TemporalUnits.YEAR; + case WEEKS: + return TemporalUnits.WEEK; + case MONTHS: + return TemporalUnits.MONTH; + case DAYS: + return TemporalUnits.DAY; + case HOURS: + return TemporalUnits.HOUR; + case MINUTES: + return TemporalUnits.MINUTE; + case SECONDS: + return TemporalUnits.SECOND; + case MILLIS: + return TemporalUnits.MILLISECOND; + } + + throw new IllegalArgumentException(String.format("Cannot create TemporalUnit from %s", chronoUnit)); + } + } + + /** + * Supported temporal units. + */ + enum TemporalUnits implements TemporalUnit { + YEAR, QUARTER, WEEK, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND + + } + @SuppressWarnings("unchecked") private static T applyTimezone(T instance, Timezone timezone) { return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java index 9c40a0b642..fa01b02b98 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetWindowFieldsOperation.java @@ -15,9 +15,11 @@ */ package org.springframework.data.mongodb.core.aggregation; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.TimeUnit; import org.bson.Document; import org.springframework.data.domain.Sort; @@ -626,7 +628,68 @@ public Document toDocument(AggregationOperationContext ctx) { * The actual time unit to apply to a {@link Window}. */ public interface WindowUnit { + String name(); + + /** + * Converts the given time unit into a {@link WindowUnit}. Supported units are: days, hours, minutes, seconds, and + * milliseconds. + * + * @param timeUnit the time unit to convert, must not be {@literal null}. + * @return + * @throws IllegalArgumentException if the {@link TimeUnit} is {@literal null} or not supported for conversion. + */ + static WindowUnit from(TimeUnit timeUnit) { + + Assert.notNull(timeUnit, "TimeUnit must not be null"); + + switch (timeUnit) { + case DAYS: + return WindowUnits.DAY; + case HOURS: + return WindowUnits.HOUR; + case MINUTES: + return WindowUnits.MINUTE; + case SECONDS: + return WindowUnits.SECOND; + case MILLISECONDS: + return WindowUnits.MILLISECOND; + } + + throw new IllegalArgumentException(String.format("Cannot create WindowUnit from %s", timeUnit)); + } + + /** + * Converts the given chrono unit into a {@link WindowUnit}. Supported units are: years, weeks, months, days, hours, + * minutes, seconds, and millis. + * + * @param chronoUnit the chrono unit to convert, must not be {@literal null}. + * @return + * @throws IllegalArgumentException if the {@link TimeUnit} is {@literal null} or not supported for conversion. + */ + static WindowUnit from(ChronoUnit chronoUnit) { + + switch (chronoUnit) { + case YEARS: + return WindowUnits.YEAR; + case WEEKS: + return WindowUnits.WEEK; + case MONTHS: + return WindowUnits.MONTH; + case DAYS: + return WindowUnits.DAY; + case HOURS: + return WindowUnits.HOUR; + case MINUTES: + return WindowUnits.MINUTE; + case SECONDS: + return WindowUnits.SECOND; + case MILLIS: + return WindowUnits.MILLISECOND; + } + + throw new IllegalArgumentException(String.format("Cannot create WindowUnit from %s", chronoUnit)); + } } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java index 95f977ed73..6d63b954f8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/DateOperatorsUnitTests.java @@ -15,14 +15,22 @@ */ package org.springframework.data.mongodb.core.aggregation; -import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.test.util.Assertions.*; + +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.TimeZone; -import org.bson.Document; import org.junit.jupiter.api.Test; + import org.springframework.data.mongodb.core.aggregation.DateOperators.Timezone; /** + * Unit tests for {@link DateOperators}. + * * @author Christoph Strobl + * @author Mark Paluch */ class DateOperatorsUnitTests { @@ -30,15 +38,15 @@ class DateOperatorsUnitTests { void rendersDateAdd() { assertThat(DateOperators.dateOf("purchaseDate").add(3, "day").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }")); + .isEqualTo("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }"); } @Test // GH-3713 void rendersDateAddWithTimezone() { assertThat(DateOperators.zonedDateOf("purchaseDate", Timezone.valueOf("America/Chicago")).add(3, "day") - .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( - "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }")); + .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( + "{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3, timezone : \"America/Chicago\" } }"); } @Test // GH-3713 @@ -46,15 +54,37 @@ void rendersDateDiff() { assertThat( DateOperators.dateOf("purchaseDate").diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document - .parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }")); + .isEqualTo("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }"); } @Test // GH-3713 void rendersDateDiffWithTimezone() { assertThat(DateOperators.zonedDateOf("purchaseDate", Timezone.valueOf("America/Chicago")) - .diffValueOf("delivered", "day").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(Document.parse( - "{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\", timezone : \"America/Chicago\" } }")); + .diffValueOf("delivered", DateOperators.TemporalUnit.from(ChronoUnit.DAYS)) + .toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo( + "{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\", timezone : \"America/Chicago\" } }"); + } + + @Test // GH-3713 + void rendersTimezoneFromZoneOffset() { + assertThat(DateOperators.Timezone.fromOffset(ZoneOffset.ofHoursMinutes(3, 30)).getValue()).isEqualTo("+03:30"); + } + + @Test // GH-3713 + void rendersTimezoneFromTimeZoneOffset() { + assertThat(DateOperators.Timezone.fromOffset(TimeZone.getTimeZone("America/Chicago")).getValue()) + .isEqualTo("-06:00"); + } + + @Test // GH-3713 + void rendersTimezoneFromTimeZoneId() { + assertThat(DateOperators.Timezone.fromZone(TimeZone.getTimeZone("America/Chicago")).getValue()) + .isEqualTo("America/Chicago"); + } + + @Test // GH-3713 + void rendersTimezoneFromZoneId() { + assertThat(DateOperators.Timezone.fromZone(ZoneId.of("America/Chicago")).getValue()).isEqualTo("America/Chicago"); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 33edab1d5a..bc8da0a3c1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1034,11 +1034,6 @@ void shouldRenderTanh() { assertThat(transform("tanh(angle)")).isEqualTo("{ \"$tanh\" : \"$angle\"}"); } - private Document transform(String expression, Object... params) { - return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); - } - - private Object transformValue(String expression, Object... params) { @Test // GH-3713 void shouldRenderDateAdd() { assertThat(transform("dateAdd(purchaseDate, 'day', 3)")).isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }")); @@ -1049,7 +1044,11 @@ void shouldRenderDateDiff() { assertThat(transform("dateDiff(purchaseDate, delivered, 'day')")).isEqualTo(Document.parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }")); } - private Object transform(String expression, Object... params) { + private Document transform(String expression, Object... params) { + return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); + } + + private Object transformValue(String expression, Object... params) { Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result); } diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index f23b290697..bc7a032e75 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -100,7 +100,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `literal` | Date Aggregation Operators -| `dayOfYear`, `dayOfMonth`, `dayOfWeek`, `year`, `month`, `week`, `hour`, `minute`, `second`, `millisecond`, `dateToString`, `dateFromString`, `dateFromParts`, `dateToParts`, `isoDayOfWeek`, `isoWeek`, `isoWeekYear` +| `dayOfYear`, `dayOfMonth`, `dayOfWeek`, `year`, `month`, `week`, `hour`, `minute`, `second`, `millisecond`, `dateAdd`, `dateDiff`, `dateToString`, `dateFromString`, `dateFromParts`, `dateToParts`, `isoDayOfWeek`, `isoWeek`, `isoWeekYear` | Variable Operators | `map` From 92cc2a582a8b5770996f11b409f9629678c2ce8e Mon Sep 17 00:00:00 2001 From: Mushtaq Ahmed Date: Sat, 31 Jul 2021 16:52:38 +0530 Subject: [PATCH 0512/1381] Add support for `$rand` aggregation operator. Closes #3724 Original pull request: #3759 --- .../core/aggregation/ArithmeticOperators.java | 25 +++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 1 + .../ArithmeticOperatorsUnitTests.java | 5 ++++ .../SpelExpressionTransformerUnitTests.java | 5 ++++ 4 files changed, 36 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 7896486abf..9610967830 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Locale; +import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Avg; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.CovariancePop; import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.CovarianceSamp; @@ -63,6 +64,16 @@ public static ArithmeticOperatorFactory valueOf(AggregationExpression expression return new ArithmeticOperatorFactory(expression); } + /** + * Creates new {@link AggregationExpression} that returns a random float between 0 and 1 each time it is called. + * + * @return new instance of {@link Rand}. + * @since 3.3 + */ + public static Rand rand() { + return new Rand(); + } + /** * @author Christoph Strobl */ @@ -2671,4 +2682,18 @@ protected String getMongoMethod() { return "$tanh"; } } + + /** + * {@link Rand} returns a floating value between 0 and 1. + * + * @author Mushtaq Ahmed + * @since 3.3 + */ + public static class Rand implements AggregationExpression { + + @Override + public Document toDocument(AggregationOperationContext context) { + return new Document("$rand", new Document()); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 6a60a7df1a..a91358353c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -99,6 +99,7 @@ public class MethodReferenceNode extends ExpressionNode { map.put("cosh", singleArgRef().forOperator("$cosh")); map.put("tan", singleArgRef().forOperator("$tan")); map.put("tanh", singleArgRef().forOperator("$tanh")); + map.put("rand", emptyRef().forOperator("$rand")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 7cde7cd1c4..b589e152aa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -166,4 +166,9 @@ void rendersTanhWithValueInDegrees() { .isEqualTo("{ $tanh : { $degreesToRadians : \"$angle\" } }"); } + + @Test // GH-3724 + void rendersRank() { + assertThat(rand().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$rand", new Document())); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index bc8da0a3c1..cc20ffd121 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1044,6 +1044,11 @@ void shouldRenderDateDiff() { assertThat(transform("dateDiff(purchaseDate, delivered, 'day')")).isEqualTo(Document.parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }")); } + @Test // GH-3724 + void shouldRenderRand() { + assertThat(transform("rand()")).isEqualTo(Document.parse("{ $rand : {} }")); + } + private Document transform(String expression, Object... params) { return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params); } From 7c6e951c7c0088459ada9e6c5a7c3ad2a427fbaa Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 25 Aug 2021 11:13:02 +0200 Subject: [PATCH 0513/1381] Polishing. Add author tags, tweak Javadoc style. Simplify tests. Document operator. See #3724 Original pull request: #3759. --- .../mongodb/core/aggregation/ArithmeticOperators.java | 4 +++- .../core/aggregation/ArithmeticOperatorsUnitTests.java | 4 ++-- .../aggregation/SpelExpressionTransformerUnitTests.java | 8 +++++--- src/main/asciidoc/reference/aggregation-framework.adoc | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 9610967830..8fe3d9120c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -40,6 +40,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Mushtaq Ahmed * @since 1.10 */ public class ArithmeticOperators { @@ -65,7 +66,8 @@ public static ArithmeticOperatorFactory valueOf(AggregationExpression expression } /** - * Creates new {@link AggregationExpression} that returns a random float between 0 and 1 each time it is called. + * Creates new {@link AggregationExpression} that returns a random float between {@code 0} and {@code 1} each time it + * is called. * * @return new instance of {@link Rand}. * @since 3.3 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index b589e152aa..02f76d5c10 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -29,6 +29,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Mushtaq Ahmed */ class ArithmeticOperatorsUnitTests { @@ -166,9 +167,8 @@ void rendersTanhWithValueInDegrees() { .isEqualTo("{ $tanh : { $degreesToRadians : \"$angle\" } }"); } - @Test // GH-3724 - void rendersRank() { + void rendersRand() { assertThat(rand().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$rand", new Document())); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index cc20ffd121..daba7a21cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1036,17 +1036,19 @@ void shouldRenderTanh() { @Test // GH-3713 void shouldRenderDateAdd() { - assertThat(transform("dateAdd(purchaseDate, 'day', 3)")).isEqualTo(Document.parse("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }")); + assertThat(transform("dateAdd(purchaseDate, 'day', 3)")) + .isEqualTo("{ $dateAdd: { startDate: \"$purchaseDate\", unit: \"day\", amount: 3 } }"); } @Test // GH-3713 void shouldRenderDateDiff() { - assertThat(transform("dateDiff(purchaseDate, delivered, 'day')")).isEqualTo(Document.parse("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }")); + assertThat(transform("dateDiff(purchaseDate, delivered, 'day')")) + .isEqualTo("{ $dateDiff: { startDate: \"$purchaseDate\", endDate: \"$delivered\", unit: \"day\" } }"); } @Test // GH-3724 void shouldRenderRand() { - assertThat(transform("rand()")).isEqualTo(Document.parse("{ $rand : {} }")); + assertThat(transform("rand()")).isEqualTo("{ $rand : {} }"); } private Document transform(String expression, Object... params) { diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index bc7a032e75..f96719adde 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -76,7 +76,7 @@ At the time of this writing, we provide support for the following Aggregation Op [cols="2*"] |=== | Pipeline Aggregation Operators -| `bucket`, `bucketAuto`, `count`, `facet`, `geoNear`, `graphLookup`, `group`, `limit`, `lookup`, `match`, `project`, `replaceRoot`, `skip`, `sort`, `unwind` +| `bucket`, `bucketAuto`, `count`, `facet`, `geoNear`, `graphLookup`, `group`, `limit`, `lookup`, `match`, `project`, `rand`, `replaceRoot`, `skip`, `sort`, `unwind` | Set Aggregation Operators | `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue` From 302c8031f90f951fcae2e67b6d471f026f266089 Mon Sep 17 00:00:00 2001 From: sangyongchoi Date: Tue, 3 Aug 2021 23:23:59 +0900 Subject: [PATCH 0514/1381] Add Criteria infix functions for `maxDistance` and `minDistance`. Closes: #3761 --- .../core/query/TypedCriteriaExtensions.kt | 22 +++++++++ .../query/TypedCriteriaExtensionsTests.kt | 48 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt index b8762ffbe1..eb1868e300 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt @@ -364,6 +364,28 @@ infix fun KProperty>.maxDistance(d: Double): Criteria = infix fun KProperty>.minDistance(d: Double): Criteria = Criteria(asString(this)).minDistance(d) +/** + * Creates a geo-spatial criterion using a $maxDistance operation, for use with $near + * + * See [MongoDB Query operator: + * $maxDistance](https://docs.mongodb.com/manual/reference/operator/query/maxDistance/) + * @author Sangyong Choi + * @since 3.2 + * @see Criteria.maxDistance + */ +infix fun Criteria.maxDistance(d: Double): Criteria = + this.maxDistance(d) + +/** + * Creates a geospatial criterion using a $minDistance operation, for use with $near or + * $nearSphere. + * @author Sangyong Choi + * @since 3.2 + * @see Criteria.minDistance + */ +infix fun Criteria.minDistance(d: Double): Criteria = + this.minDistance(d) + /** * Creates a criterion using the $elemMatch operator * diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt index 54969476d3..3b9dfc9342 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt @@ -317,6 +317,54 @@ class TypedCriteriaExtensionsTests { assertThat(typed).isEqualTo(expected) } + @Test + fun `maxDistance() should equal expected criteria with nearSphere`() { + val point = Point(0.0, 0.0) + + val typed = Building::location nearSphere point maxDistance 3.0 + val expected = Criteria("location") + .nearSphere(point) + .maxDistance(3.0) + + assertThat(typed).isEqualTo(expected) + } + + @Test + fun `minDistance() should equal expected criteria with nearSphere`() { + val point = Point(0.0, 0.0) + + val typed = Building::location nearSphere point minDistance 3.0 + val expected = Criteria("location") + .nearSphere(point) + .minDistance(3.0) + + assertThat(typed).isEqualTo(expected) + } + + @Test + fun `maxDistance() should equal expected criteria with near`() { + val point = Point(0.0, 0.0) + + val typed = Building::location near point maxDistance 3.0 + val expected = Criteria("location") + .near(point) + .maxDistance(3.0) + + assertThat(typed).isEqualTo(expected) + } + + @Test + fun `minDistance() should equal expected criteria with near`() { + val point = Point(0.0, 0.0) + + val typed = Building::location near point minDistance 3.0 + val expected = Criteria("location") + .near(point) + .minDistance(3.0) + + assertThat(typed).isEqualTo(expected) + } + @Test fun `elemMatch() should equal expected criteria`() { From 467536cb34162f528ecba3d494e77414bb2cb333 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 25 Aug 2021 14:33:06 +0200 Subject: [PATCH 0515/1381] Polishing. Update since version. Reformat code. See: #3761. --- .../mongodb/core/query/TypedCriteriaExtensions.kt | 4 ++-- .../core/query/TypedCriteriaExtensionsTests.kt | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt index eb1868e300..ab7e32fc03 100644 --- a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt +++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensions.kt @@ -370,7 +370,7 @@ infix fun KProperty>.minDistance(d: Double): Criteria = * See [MongoDB Query operator: * $maxDistance](https://docs.mongodb.com/manual/reference/operator/query/maxDistance/) * @author Sangyong Choi - * @since 3.2 + * @since 3.2.5 * @see Criteria.maxDistance */ infix fun Criteria.maxDistance(d: Double): Criteria = @@ -380,7 +380,7 @@ infix fun Criteria.maxDistance(d: Double): Criteria = * Creates a geospatial criterion using a $minDistance operation, for use with $near or * $nearSphere. * @author Sangyong Choi - * @since 3.2 + * @since 3.2.5 * @see Criteria.minDistance */ infix fun Criteria.minDistance(d: Double): Criteria = diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt index 3b9dfc9342..7a5c358fad 100644 --- a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt +++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/query/TypedCriteriaExtensionsTests.kt @@ -25,8 +25,11 @@ import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type import java.util.regex.Pattern /** + * Unit tests for [Criteria] extensions. + * * @author Tjeu Kayim * @author Mark Paluch + * @author Sangyong Choi */ class TypedCriteriaExtensionsTests { @@ -319,8 +322,8 @@ class TypedCriteriaExtensionsTests { @Test fun `maxDistance() should equal expected criteria with nearSphere`() { - val point = Point(0.0, 0.0) + val point = Point(0.0, 0.0) val typed = Building::location nearSphere point maxDistance 3.0 val expected = Criteria("location") .nearSphere(point) @@ -331,8 +334,8 @@ class TypedCriteriaExtensionsTests { @Test fun `minDistance() should equal expected criteria with nearSphere`() { - val point = Point(0.0, 0.0) + val point = Point(0.0, 0.0) val typed = Building::location nearSphere point minDistance 3.0 val expected = Criteria("location") .nearSphere(point) @@ -343,8 +346,8 @@ class TypedCriteriaExtensionsTests { @Test fun `maxDistance() should equal expected criteria with near`() { - val point = Point(0.0, 0.0) + val point = Point(0.0, 0.0) val typed = Building::location near point maxDistance 3.0 val expected = Criteria("location") .near(point) @@ -355,8 +358,8 @@ class TypedCriteriaExtensionsTests { @Test fun `minDistance() should equal expected criteria with near`() { - val point = Point(0.0, 0.0) + val point = Point(0.0, 0.0) val typed = Building::location near point minDistance 3.0 val expected = Criteria("location") .near(point) From 36e2d80d71634a134ed2c6d615be217692b59e9a Mon Sep 17 00:00:00 2001 From: Ivan Volzhev Date: Sat, 21 Aug 2021 08:24:22 +0200 Subject: [PATCH 0516/1381] Relax requirement for GeoJsonMultiPoint construction allowing creation using a single point. Only 1 point is required per GeoJson RFC and Mongo works just fine with 1 point as well. Closes #3776 Original pull request: #3777. --- .../mongodb/core/geo/GeoJsonMultiPoint.java | 18 ++++++++++++++++-- .../data/mongodb/core/geo/GeoJsonTests.java | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java index f42d38e0dc..c1c80b89e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java @@ -28,6 +28,7 @@ * {@link GeoJsonMultiPoint} is defined as list of {@link Point}s. * * @author Christoph Strobl + * @author Ivan Volzhev * @since 1.7 * @see https://geojson.org/geojson-spec.html#multipoint */ @@ -40,12 +41,12 @@ public class GeoJsonMultiPoint implements GeoJson> { /** * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}s. * - * @param points points must not be {@literal null} and have at least 2 entries. + * @param points points must not be {@literal null} and have at least 1 entry. */ public GeoJsonMultiPoint(List points) { Assert.notNull(points, "Points must not be null."); - Assert.isTrue(points.size() >= 2, "Minimum of 2 Points required."); + Assert.isTrue(points.size() >= 1, "Minimum of 1 Point required."); this.points = new ArrayList(points); } @@ -69,6 +70,19 @@ public GeoJsonMultiPoint(Point first, Point second, Point... others) { this.points.addAll(Arrays.asList(others)); } + /** + * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}. + * + * @param point must not be {@literal null}. + */ + public GeoJsonMultiPoint(Point point) { + + Assert.notNull(point, "First point must not be null!"); + + this.points = new ArrayList(); + this.points.add(point); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.geo.GeoJson#getType() diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index fa7115c098..6fa053dacd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -63,6 +63,7 @@ /** * @author Christoph Strobl * @author Mark Paluch + * @author Ivan Volzhev */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration @@ -329,6 +330,21 @@ public void shouldSaveAndRetrieveDocumentWithGeoJsonMultiPointTypeCorrectly() { assertThat(result.geoJsonMultiPoint).isEqualTo(obj.geoJsonMultiPoint); } + @Test // DATAMONGO-3776 + public void shouldSaveAndRetrieveDocumentWithGeoJsonMultiPointTypeWithOnePointCorrectly() { + + DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType(); + obj.id = "geoJsonMultiPoint"; + obj.geoJsonMultiPoint = new GeoJsonMultiPoint(new Point(0, 0)); + + template.save(obj); + + DocumentWithPropertyUsingGeoJsonType result = template.findOne(query(where("id").is(obj.id)), + DocumentWithPropertyUsingGeoJsonType.class); + + assertThat(result.geoJsonMultiPoint).isEqualTo(obj.geoJsonMultiPoint); + } + @Test // DATAMONGO-1137 public void shouldSaveAndRetrieveDocumentWithGeoJsonMultiPolygonTypeCorrectly() { From f71f1074455042e774030314e208950d9e570fad Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 25 Aug 2021 14:57:02 +0200 Subject: [PATCH 0517/1381] Polishing. Reorder methods. Add since tag. Simplify assertions. Use diamond syntax. See: #3776 Original pull request: #3777. --- .../mongodb/core/geo/GeoJsonMultiPoint.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java index c1c80b89e8..30af9f7293 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPoint.java @@ -38,17 +38,31 @@ public class GeoJsonMultiPoint implements GeoJson> { private final List points; + /** + * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}. + * + * @param point must not be {@literal null}. + * @since 3.2.5 + */ + public GeoJsonMultiPoint(Point point) { + + Assert.notNull(point, "Point must not be null!"); + + this.points = new ArrayList<>(); + this.points.add(point); + } + /** * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}s. * - * @param points points must not be {@literal null} and have at least 1 entry. + * @param points points must not be {@literal null} and not empty */ public GeoJsonMultiPoint(List points) { - Assert.notNull(points, "Points must not be null."); - Assert.isTrue(points.size() >= 1, "Minimum of 1 Point required."); + Assert.notNull(points, "Points must not be null!"); + Assert.notEmpty(points, "Points must contain at least one point!"); - this.points = new ArrayList(points); + this.points = new ArrayList<>(points); } /** @@ -64,25 +78,12 @@ public GeoJsonMultiPoint(Point first, Point second, Point... others) { Assert.notNull(second, "Second point must not be null!"); Assert.notNull(others, "Additional points must not be null!"); - this.points = new ArrayList(); + this.points = new ArrayList<>(); this.points.add(first); this.points.add(second); this.points.addAll(Arrays.asList(others)); } - /** - * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}. - * - * @param point must not be {@literal null}. - */ - public GeoJsonMultiPoint(Point point) { - - Assert.notNull(point, "First point must not be null!"); - - this.points = new ArrayList(); - this.points.add(point); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.geo.GeoJson#getType() From 297ef9823920008245f6271acc1e1212991d89e0 Mon Sep 17 00:00:00 2001 From: divya srivastava Date: Mon, 23 Aug 2021 17:33:06 +0530 Subject: [PATCH 0518/1381] Add support for `$regexFind`, `$regexFindAll`, and `$regexMatch` aggregation operators. Closes #3725 Original pull request: #3781. --- .../core/aggregation/StringOperators.java | 438 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 3 + .../ProjectionOperationUnitTests.java | 27 ++ .../SpelExpressionTransformerUnitTests.java | 64 +++ .../aggregation/StringOperatorsUnitTests.java | 106 +++++ 5 files changed, 638 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java index 5a31f6b3fc..710c6c855e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java @@ -515,6 +515,120 @@ public RTrim rtrim(AggregationExpression expression) { private RTrim createRTrim() { return usesFieldRef() ? RTrim.valueOf(fieldReference) : RTrim.valueOf(expression); } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given + * regular expression to find the document with the first match.
      + * NOTE: Requires MongoDB 4.0 or later. + * + * @return new instance of {@link RegexFind}. + */ + public RegexFind regexFind(String regex) { + return createRegexFind().regex(regex); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression resulting from the given {@link AggregationExpression} to find the document with the first match.
      + * NOTE: Requires MongoDB 4.0 or later. + * + * @return new instance of {@link RegexFind}. + */ + public RegexFind regexFind(AggregationExpression expression) { + return createRegexFind().regexOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression with the options specified in the argument to find the document with the first match. + * + * @param regex the regular expression to apply + * @param options the options to use + * @return new instance of {@link RegexFind}. + */ + public RegexFind regexFind(String regex,String options) { + return createRegexFind().regex(regex).options(options); + } + + private RegexFind createRegexFind() { + return usesFieldRef() ? RegexFind.valueOf(fieldReference) : RegexFind.valueOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given + * regular expression to find all the documents with the match.
      + * NOTE: Requires MongoDB 4.0 or later. + * + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll regexFindAll(String regex) { + return createRegexFindAll().regex(regex); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression resulting from the given {@link AggregationExpression} to find all the documents with the match..
      + * NOTE: Requires MongoDB 4.0 or later. + * + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll regexFindAll(AggregationExpression expression) { + return createRegexFindAll().regexOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression with the options specified in the argument to find all the documents with the match.. + * + * @param regex the regular expression to apply + * @param options the options to use + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll regexFindAll(String regex,String options) { + return createRegexFindAll().regex(regex).options(options); + } + + private RegexFindAll createRegexFindAll() { + return usesFieldRef() ? RegexFindAll.valueOf(fieldReference) : RegexFindAll.valueOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given + * regular expression to find if a match is found or not.
      + * NOTE: Requires MongoDB 4.0 or later. + * + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch regexMatch(String regex) { + return createRegexMatch().regex(regex); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression resulting from the given {@link AggregationExpression} to find if a match is found or not.
      + * NOTE: Requires MongoDB 4.0 or later. + * + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch regexMatch(AggregationExpression expression) { + return createRegexMatch().regexOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression with the options specified in the argument to find if a match is found or not. + * + * @param regex the regular expression to apply + * @param options the options to use + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch regexMatch(String regex,String options) { + return createRegexMatch().regex(regex).options(options); + } + + private RegexMatch createRegexMatch() { + return usesFieldRef() ? RegexMatch.valueOf(fieldReference) : RegexMatch.valueOf(expression); + } private boolean usesFieldRef() { return fieldReference != null; @@ -1477,4 +1591,328 @@ protected String getMongoMethod() { return "$rtrim"; } } + + /** + * {@link AggregationExpression} for {@code $regexFind} which applies a regular expression (regex) to a string and + * returns information on the first matched substring.
      + * NOTE: Requires MongoDB 4.0 or later. + * + */ + public static class RegexFind extends AbstractAggregationExpression { + + protected RegexFind(Object value) { + super(value); + } + + @Override + protected String getMongoMethod() { + return "$regexFind"; + } + + /** + * Creates new {@link RegexFind} using the value of the provided {@link Field fieldReference} as {@literal input} value. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public static RegexFind valueOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexFind(Collections.singletonMap("input", Fields.field(fieldReference))); + } + + /** + * Creates new {@link RegexFind} using the result of the provided {@link AggregationExpression} as {@literal input} + * value. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public static RegexFind valueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFind(Collections.singletonMap("input", expression)); + } + + /** + * Optional specify the options to use with the regular expression. + * + * @param options must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind options(String options) { + Assert.notNull(options, "Options must not be null!"); + return new RegexFind(append("options", options)); + } + + /** + * Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind optionsOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexFind(append("options", Fields.field(fieldReference))); + } + + /** + * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind optionsOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFind(append("options", expression)); + } + + /** + * Optional specify the regular expression to apply. + * + * @param regex must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind regex(String regex) { + Assert.notNull(regex, "Regex must not be null!"); + return new RegexFind(append("regex",regex)); + } + + /** + * Optional specify the reference to the {@link Field field} holding the regular expression to apply. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind regexOf(String fieldReference) { + Assert.notNull(fieldReference, "fieldReference must not be null!"); + return new RegexFind(append("regex",Fields.field(fieldReference))); + } + + /** + * Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind regexOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFind(append("regex",expression)); + } + + } + + /** + * {@link AggregationExpression} for {@code $regexFindAll} which applies a regular expression (regex) to a string and + * returns information on all the matched substrings.
      + * NOTE: Requires MongoDB 4.0 or later. + * + */ + public static class RegexFindAll extends AbstractAggregationExpression { + + protected RegexFindAll(Object value) { + super(value); + } + + @Override + protected String getMongoMethod() { + return "$regexFindAll"; + } + + /** + * Creates new {@link RegexFindAll} using the value of the provided {@link Field fieldReference} as {@literal input} value. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public static RegexFindAll valueOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexFindAll(Collections.singletonMap("input", Fields.field(fieldReference))); + } + + /** + * Creates new {@link RegexFindAll} using the result of the provided {@link AggregationExpression} as {@literal input} + * value. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public static RegexFindAll valueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFindAll(Collections.singletonMap("input", expression)); + } + + /** + * Optional specify the options to use with the regular expression. + * + * @param options must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll options(String options) { + Assert.notNull(options, "Options must not be null!"); + return new RegexFindAll(append("options", options)); + } + + /** + * Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll optionsOf(String fieldReference) { + Assert.notNull(fieldReference, "fieldReference must not be null!"); + return new RegexFindAll(append("options", Fields.field(fieldReference))); + } + + /** + * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll optionsOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFindAll(append("options", expression)); + } + + /** + * Optional specify the regular expression to apply. + * + * @param regex must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll regex(String regex) { + Assert.notNull(regex, "Regex must not be null!"); + return new RegexFindAll(append("regex",regex)); + } + + /** + * Optional specify the reference to the {@link Field field} holding the regular expression to apply. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll regexOf(String fieldReference) { + Assert.notNull(fieldReference, "fieldReference must not be null!"); + return new RegexFindAll(append("regex",Fields.field(fieldReference))); + } + + /** + * Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll regexOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFindAll(append("regex",expression)); + } + + } + + /** + * {@link AggregationExpression} for {@code $regexMatch} which applies a regular expression (regex) to a string and + * returns a boolean that indicates if a match is found or not.
      + * NOTE: Requires MongoDB 4.0 or later. + * + */ + public static class RegexMatch extends AbstractAggregationExpression { + + protected RegexMatch(Object value) { + super(value); + } + + @Override + protected String getMongoMethod() { + return "$regexMatch"; + } + + /** + * Creates new {@link RegexMatch} using the value of the provided {@link Field fieldReference} as {@literal input} value. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public static RegexMatch valueOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexMatch(Collections.singletonMap("input", Fields.field(fieldReference))); + } + + /** + * Creates new {@link RegexMatch} using the result of the provided {@link AggregationExpression} as {@literal input} + * value. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public static RegexMatch valueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexMatch(Collections.singletonMap("input", expression)); + } + + /** + * Optional specify the options to use with the regular expression. + * + * @param options must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch options(String options) { + Assert.notNull(options, "Options must not be null!"); + return new RegexMatch(append("options", options)); + } + + /** + * Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch optionsOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexMatch(append("options", Fields.field(fieldReference))); + } + + /** + * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch optionsOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexMatch(append("options", expression)); + } + + /** + * Optional specify the regular expression to apply. + * + * @param regex must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch regex(String regex) { + Assert.notNull(regex, "Regex must not be null!"); + return new RegexMatch(append("regex",regex)); + } + + /** + * Optional specify the reference to the {@link Field field} holding the regular expression to apply. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch regexOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexMatch(append("regex",Fields.field(fieldReference))); + } + + /** + * Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch regexOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexMatch(append("regex",expression)); + } + + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index a91358353c..0fbfe51f09 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -116,6 +116,9 @@ public class MethodReferenceNode extends ExpressionNode { map.put("trim", mapArgRef().forOperator("$trim").mappingParametersTo("input", "chars")); map.put("ltrim", mapArgRef().forOperator("$ltrim").mappingParametersTo("input", "chars")); map.put("rtrim", mapArgRef().forOperator("$rtrim").mappingParametersTo("input", "chars")); + map.put("regexFind", mapArgRef().forOperator("$regexFind").mappingParametersTo("input", "regex" , "options")); + map.put("regexFindAll", mapArgRef().forOperator("$regexFindAll").mappingParametersTo("input", "regex" , "options")); + map.put("regexMatch", mapArgRef().forOperator("$regexMatch").mappingParametersTo("input", "regex" , "options")); // TEXT SEARCH OPERATORS map.put("meta", singleArgRef().forOperator("$meta")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index 805fc10f38..ff6771d9f1 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -1766,6 +1766,33 @@ public void shouldRenderSubstrCPCorrectly() { assertThat(agg) .isEqualTo(Document.parse("{ $project : { yearSubstring: { $substrCP: [ \"$quarter\", 0, 2 ] } } }")); } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindCorrectly() { + + Document agg = project().and(StringOperators.valueOf("field1").regexFind("e")).as("regex") + .toDocument(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg).isEqualTo(Document.parse("{ $project : { regex: { $regexFind: { \"input\" : \"$field1\", \"regex\" : \"e\" } } } }")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindAllCorrectly() { + + Document agg = project().and(StringOperators.valueOf("field1").regexFindAll("e")).as("regex") + .toDocument(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg).isEqualTo(Document.parse("{ $project : { regex: { $regexFindAll: { \"input\" : \"$field1\", \"regex\" : \"e\" } } } }")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexMatchCorrectly() { + + Document agg = project().and(StringOperators.valueOf("field1").regexMatch("e")).as("regex") + .toDocument(Aggregation.DEFAULT_CONTEXT); + + assertThat(agg).isEqualTo(Document.parse("{ $project : { regex: { $regexMatch: { \"input\" : \"$field1\", \"regex\" : \"e\" } } } }")); + } @Test // DATAMONGO-1548 public void shouldRenderIndexOfArrayCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index daba7a21cd..41b0323636 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -800,6 +800,70 @@ void shouldRenderRtrimWithCharsFromFieldReference() { assertThat(transform("rtrim(field1, field2)")) .isEqualTo("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}"); } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexFindWithoutOptions() { + + assertThat(transform("regexFind(field1,'e')")) + .isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexFindWithOptions() { + + assertThat(transform("regexFind(field1,'e','i')")) + .isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexFindWithOptionsFromFieldReference() { + + assertThat(transform("regexFind(field1,'e',field2)")) + .isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexFindAllWithoutOptions() { + + assertThat(transform("regexFindAll(field1,'e')")) + .isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexFindAllWithOptions() { + + assertThat(transform("regexFindAll(field1,'e','i')")) + .isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexFindAllWithOptionsFromFieldReference() { + + assertThat(transform("regexFindAll(field1,'e',field2)")) + .isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexMatchWithoutOptions() { + + assertThat(transform("regexMatch(field1,'e')")) + .isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexMatchWithOptions() { + + assertThat(transform("regexMatch(field1,'e','i')")) + .isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}")); + } + + @Test // DATAMONGO-3725 + public void shouldRenderRegexMatchWithOptionsFromFieldReference() { + + assertThat(transform("regexMatch(field1,'e',field2)")) + .isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}")); + } + @Test // DATAMONGO-2077 void shouldRenderConvertWithoutOptionalParameters() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java index 0dbe362ae4..cdd0b38dbc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java @@ -144,5 +144,111 @@ public void shouldRenderRTrimWithCharsExpression() { assertThat(StringOperators.valueOf("shrewd").rtrim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ")); } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindAll() { + + assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindAllForExpression() { + + assertThat(StringOperators.valueOf(EXPRESSION).regexFindAll("e").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindAllForRegexExpression() { + + assertThat(StringOperators.valueOf("shrewd").regexFindAll(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindAllWithOptions() { + + assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindAllWithOptionsExpression() { + + assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexMatch() { + + assertThat(StringOperators.valueOf("shrewd").regexMatch("e").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexMatchForExpression() { + + assertThat(StringOperators.valueOf(EXPRESSION).regexMatch("e").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexMatchForRegexExpression() { + + assertThat(StringOperators.valueOf("shrewd").regexMatch(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexMatchWithOptions() { + + assertThat(StringOperators.valueOf("shrewd").regexMatch("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexMatchWithOptionsExpression() { + + assertThat(StringOperators.valueOf("shrewd").regexMatch("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFind() { + + assertThat(StringOperators.valueOf("shrewd").regexFind("e").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindForExpression() { + + assertThat(StringOperators.valueOf(EXPRESSION).regexFind("e").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFind: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindForRegexExpression() { + + assertThat(StringOperators.valueOf("shrewd").regexFind(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindWithOptions() { + + assertThat(StringOperators.valueOf("shrewd").regexFind("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ")); + } + + @Test // DATAMONGO - 3725 + public void shouldRenderRegexFindWithOptionsExpression() { + + assertThat(StringOperators.valueOf("shrewd").regexFind("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } ")); + } + } From 69b582823a53cf3a1b8a07354da942bd94432f4f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 26 Aug 2021 12:20:11 +0200 Subject: [PATCH 0519/1381] Polishing. Add support for Pattern. Extract Regex flags translation from Criteria into RegexFlags utility class. Add since and author tags. Simplify tests. Update reference documentation. See #3725. Original pull request: #3781. --- .../core/aggregation/StringOperators.java | 371 ++++++++++----- .../data/mongodb/core/query/Criteria.java | 58 +-- .../data/mongodb/util/RegexFlags.java | 116 +++++ .../ProjectionOperationUnitTests.java | 433 +++++++++--------- .../SpelExpressionTransformerUnitTests.java | 89 ++-- .../aggregation/StringOperatorsUnitTests.java | 226 +++++---- .../reference/aggregation-framework.adoc | 2 +- 7 files changed, 776 insertions(+), 519 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java index 710c6c855e..8b6bb03875 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java @@ -18,8 +18,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; import org.springframework.data.domain.Range; +import org.springframework.data.mongodb.util.RegexFlags; import org.springframework.util.Assert; /** @@ -27,6 +30,7 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Divya Srivastava * @since 1.10 */ public class StringOperators { @@ -515,117 +519,170 @@ public RTrim rtrim(AggregationExpression expression) { private RTrim createRTrim() { return usesFieldRef() ? RTrim.valueOf(fieldReference) : RTrim.valueOf(expression); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given * regular expression to find the document with the first match.
      * NOTE: Requires MongoDB 4.0 or later. * + * @param regex must not be {@literal null}. * @return new instance of {@link RegexFind}. + * @since 3.3 */ public RegexFind regexFind(String regex) { return createRegexFind().regex(regex); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular - * expression resulting from the given {@link AggregationExpression} to find the document with the first match.
      + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression resulting from the given {@link AggregationExpression} to find the document with the first + * match.
      * NOTE: Requires MongoDB 4.0 or later. * + * @param expression must not be {@literal null}. * @return new instance of {@link RegexFind}. + * @since 3.3 */ public RegexFind regexFind(AggregationExpression expression) { return createRegexFind().regexOf(expression); } - + + /** + * Creates new {@link AggregationExpression} that takes the {@link Pattern} and applies the regular expression with + * the options specified in the argument to find the document with the first match. + * + * @param pattern the pattern object to apply. + * @return new instance of {@link RegexFind}. + * @since 3.3 + */ + public RegexFind regexFind(Pattern pattern) { + return createRegexFind().pattern(pattern); + } + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular * expression with the options specified in the argument to find the document with the first match. * - * @param regex the regular expression to apply - * @param options the options to use + * @param regex the regular expression to apply. + * @param options the options to use. * @return new instance of {@link RegexFind}. + * @since 3.3 */ - public RegexFind regexFind(String regex,String options) { + public RegexFind regexFind(String regex, String options) { return createRegexFind().regex(regex).options(options); } - + private RegexFind createRegexFind() { return usesFieldRef() ? RegexFind.valueOf(fieldReference) : RegexFind.valueOf(expression); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given * regular expression to find all the documents with the match.
      * NOTE: Requires MongoDB 4.0 or later. * + * @param regex must not be {@literal null}. * @return new instance of {@link RegexFindAll}. + * @since 3.3 */ public RegexFindAll regexFindAll(String regex) { return createRegexFindAll().regex(regex); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular - * expression resulting from the given {@link AggregationExpression} to find all the documents with the match..
      + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression resulting from the given {@link AggregationExpression} to find all the documents with the + * match..
      * NOTE: Requires MongoDB 4.0 or later. * + * @param expression must not be {@literal null}. * @return new instance of {@link RegexFindAll}. + * @since 3.3 */ public RegexFindAll regexFindAll(AggregationExpression expression) { return createRegexFindAll().regexOf(expression); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular - * expression with the options specified in the argument to find all the documents with the match.. + * Creates new {@link AggregationExpression} that takes a {@link Pattern} and applies the regular expression with + * the options specified in the argument to find all the documents with the match. * - * @param regex the regular expression to apply - * @param options the options to use + * @param pattern the pattern object to apply. * @return new instance of {@link RegexFindAll}. + * @since 3.3 */ - public RegexFindAll regexFindAll(String regex,String options) { + public RegexFindAll regexFindAll(Pattern pattern) { + return createRegexFindAll().pattern(pattern); + } + + /** + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * expression with the options specified in the argument to find all the documents with the match. + * + * @param regex the regular expression to apply. + * @param options the options to use. + * @return new instance of {@link RegexFindAll}. + * @since 3.3 + */ + public RegexFindAll regexFindAll(String regex, String options) { return createRegexFindAll().regex(regex).options(options); } - + private RegexFindAll createRegexFindAll() { return usesFieldRef() ? RegexFindAll.valueOf(fieldReference) : RegexFindAll.valueOf(expression); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the given * regular expression to find if a match is found or not.
      * NOTE: Requires MongoDB 4.0 or later. * + * @param regex must not be {@literal null}. * @return new instance of {@link RegexMatch}. + * @since 3.3 */ public RegexMatch regexMatch(String regex) { return createRegexMatch().regex(regex); } - + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular * expression resulting from the given {@link AggregationExpression} to find if a match is found or not.
      * NOTE: Requires MongoDB 4.0 or later. * + * @param expression must not be {@literal null}. * @return new instance of {@link RegexMatch}. + * @since 3.3 */ public RegexMatch regexMatch(AggregationExpression expression) { return createRegexMatch().regexOf(expression); } - + + /** + * Creates new {@link AggregationExpression} that takes a {@link Pattern} and applies the regular expression with + * the options specified in the argument to find if a match is found or not. + * + * @param pattern the pattern object to apply. + * @return new instance of {@link RegexMatch}. + * @since 3.3 + */ + public RegexMatch regexMatch(Pattern pattern) { + return createRegexMatch().pattern(pattern); + } + /** - * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular + * Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular * expression with the options specified in the argument to find if a match is found or not. * - * @param regex the regular expression to apply - * @param options the options to use + * @param regex the regular expression to apply. + * @param options the options to use. * @return new instance of {@link RegexMatch}. + * @since 3.3 */ - public RegexMatch regexMatch(String regex,String options) { + public RegexMatch regexMatch(String regex, String options) { return createRegexMatch().regex(regex).options(options); } - + private RegexMatch createRegexMatch() { return usesFieldRef() ? RegexMatch.valueOf(fieldReference) : RegexMatch.valueOf(expression); } @@ -1591,35 +1648,35 @@ protected String getMongoMethod() { return "$rtrim"; } } - + /** - * {@link AggregationExpression} for {@code $regexFind} which applies a regular expression (regex) to a string and + * {@link AggregationExpression} for {@code $regexFind} which applies a regular expression (regex) to a string and * returns information on the first matched substring.
      * NOTE: Requires MongoDB 4.0 or later. * + * @author Divya Srivastava + * @since 3.3 */ public static class RegexFind extends AbstractAggregationExpression { - + protected RegexFind(Object value) { super(value); } - @Override - protected String getMongoMethod() { - return "$regexFind"; - } - /** - * Creates new {@link RegexFind} using the value of the provided {@link Field fieldReference} as {@literal input} value. + * Creates new {@link RegexFind} using the value of the provided {@link Field fieldReference} as {@literal input} + * value. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexFind}. */ public static RegexFind valueOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexFind(Collections.singletonMap("input", Fields.field(fieldReference))); } - + /** * Creates new {@link RegexFind} using the result of the provided {@link AggregationExpression} as {@literal input} * value. @@ -1628,10 +1685,12 @@ public static RegexFind valueOf(String fieldReference) { * @return new instance of {@link RegexFind}. */ public static RegexFind valueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFind(Collections.singletonMap("input", expression)); } - + /** * Optional specify the options to use with the regular expression. * @@ -1639,72 +1698,108 @@ public static RegexFind valueOf(AggregationExpression expression) { * @return new instance of {@link RegexFind}. */ public RegexFind options(String options) { + Assert.notNull(options, "Options must not be null!"); + return new RegexFind(append("options", options)); } - + /** - * Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression. + * Optional specify the reference to the {@link Field field} holding the options values to use with the regular + * expression. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexFind}. */ public RegexFind optionsOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexFind(append("options", Fields.field(fieldReference))); } - + /** - * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression. + * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular + * expression. * * @param expression must not be {@literal null}. * @return new instance of {@link RegexFind}. */ public RegexFind optionsOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFind(append("options", expression)); } - + /** - * Optional specify the regular expression to apply. + * Specify the regular expression to apply. * * @param regex must not be {@literal null}. * @return new instance of {@link RegexFind}. */ public RegexFind regex(String regex) { + Assert.notNull(regex, "Regex must not be null!"); - return new RegexFind(append("regex",regex)); + + return new RegexFind(append("regex", regex)); } - + /** - * Optional specify the reference to the {@link Field field} holding the regular expression to apply. + * Apply a {@link Pattern} into {@code regex} and {@code options} fields. + * + * @param pattern must not be {@literal null}. + * @return new instance of {@link RegexFind}. + */ + public RegexFind pattern(Pattern pattern) { + + Assert.notNull(pattern, "Pattern must not be null!"); + + Map regex = append("regex", pattern.pattern()); + regex.put("options", RegexFlags.toRegexOptions(pattern.flags())); + + return new RegexFind(regex); + } + + /** + * Specify the reference to the {@link Field field} holding the regular expression to apply. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexFind}. */ public RegexFind regexOf(String fieldReference) { + Assert.notNull(fieldReference, "fieldReference must not be null!"); - return new RegexFind(append("regex",Fields.field(fieldReference))); + + return new RegexFind(append("regex", Fields.field(fieldReference))); } - + /** - * Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply. + * Specify the {@link AggregationExpression} evaluating to the regular expression to apply. * * @param expression must not be {@literal null}. * @return new instance of {@link RegexFind}. */ public RegexFind regexOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); - return new RegexFind(append("regex",expression)); + + return new RegexFind(append("regex", expression)); } + @Override + protected String getMongoMethod() { + return "$regexFind"; + } } - + /** - * {@link AggregationExpression} for {@code $regexFindAll} which applies a regular expression (regex) to a string and + * {@link AggregationExpression} for {@code $regexFindAll} which applies a regular expression (regex) to a string and * returns information on all the matched substrings.
      * NOTE: Requires MongoDB 4.0 or later. * + * @author Divya Srivastava + * @since 3.3 */ public static class RegexFindAll extends AbstractAggregationExpression { @@ -1712,13 +1807,9 @@ protected RegexFindAll(Object value) { super(value); } - @Override - protected String getMongoMethod() { - return "$regexFindAll"; - } - /** - * Creates new {@link RegexFindAll} using the value of the provided {@link Field fieldReference} as {@literal input} value. + * Creates new {@link RegexFindAll} using the value of the provided {@link Field fieldReference} as {@literal input} + * value. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexFindAll}. @@ -1727,19 +1818,21 @@ public static RegexFindAll valueOf(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new RegexFindAll(Collections.singletonMap("input", Fields.field(fieldReference))); } - + /** - * Creates new {@link RegexFindAll} using the result of the provided {@link AggregationExpression} as {@literal input} - * value. + * Creates new {@link RegexFindAll} using the result of the provided {@link AggregationExpression} as + * {@literal input} value. * * @param expression must not be {@literal null}. * @return new instance of {@link RegexFindAll}. */ public static RegexFindAll valueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFindAll(Collections.singletonMap("input", expression)); } - + /** * Optional specify the options to use with the regular expression. * @@ -1747,72 +1840,108 @@ public static RegexFindAll valueOf(AggregationExpression expression) { * @return new instance of {@link RegexFindAll}. */ public RegexFindAll options(String options) { + Assert.notNull(options, "Options must not be null!"); + return new RegexFindAll(append("options", options)); } - + /** - * Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression. + * Optional specify the reference to the {@link Field field} holding the options values to use with the regular + * expression. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexFindAll}. */ public RegexFindAll optionsOf(String fieldReference) { + Assert.notNull(fieldReference, "fieldReference must not be null!"); + return new RegexFindAll(append("options", Fields.field(fieldReference))); } - + /** - * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression. + * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular + * expression. * * @param expression must not be {@literal null}. * @return new instance of {@link RegexFindAll}. */ public RegexFindAll optionsOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexFindAll(append("options", expression)); } - + /** - * Optional specify the regular expression to apply. + * Apply a {@link Pattern} into {@code regex} and {@code options} fields. + * + * @param pattern must not be {@literal null}. + * @return new instance of {@link RegexFindAll}. + */ + public RegexFindAll pattern(Pattern pattern) { + + Assert.notNull(pattern, "Pattern must not be null!"); + + Map regex = append("regex", pattern.pattern()); + regex.put("options", RegexFlags.toRegexOptions(pattern.flags())); + + return new RegexFindAll(regex); + } + + /** + * Specify the regular expression to apply. * * @param regex must not be {@literal null}. * @return new instance of {@link RegexFindAll}. */ public RegexFindAll regex(String regex) { + Assert.notNull(regex, "Regex must not be null!"); - return new RegexFindAll(append("regex",regex)); + + return new RegexFindAll(append("regex", regex)); } - + /** - * Optional specify the reference to the {@link Field field} holding the regular expression to apply. + * Specify the reference to the {@link Field field} holding the regular expression to apply. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexFindAll}. */ public RegexFindAll regexOf(String fieldReference) { + Assert.notNull(fieldReference, "fieldReference must not be null!"); - return new RegexFindAll(append("regex",Fields.field(fieldReference))); + + return new RegexFindAll(append("regex", Fields.field(fieldReference))); } - + /** - * Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply. + * Specify the {@link AggregationExpression} evaluating to the regular expression to apply. * * @param expression must not be {@literal null}. * @return new instance of {@link RegexFindAll}. */ public RegexFindAll regexOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); - return new RegexFindAll(append("regex",expression)); + + return new RegexFindAll(append("regex", expression)); } + @Override + protected String getMongoMethod() { + return "$regexFindAll"; + } } - + /** - * {@link AggregationExpression} for {@code $regexMatch} which applies a regular expression (regex) to a string and + * {@link AggregationExpression} for {@code $regexMatch} which applies a regular expression (regex) to a string and * returns a boolean that indicates if a match is found or not.
      * NOTE: Requires MongoDB 4.0 or later. * + * @author Divya Srivastava + * @since 3.3 */ public static class RegexMatch extends AbstractAggregationExpression { @@ -1820,22 +1949,20 @@ protected RegexMatch(Object value) { super(value); } - @Override - protected String getMongoMethod() { - return "$regexMatch"; - } - /** - * Creates new {@link RegexMatch} using the value of the provided {@link Field fieldReference} as {@literal input} value. + * Creates new {@link RegexMatch} using the value of the provided {@link Field fieldReference} as {@literal input} + * value. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexMatch}. */ public static RegexMatch valueOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexMatch(Collections.singletonMap("input", Fields.field(fieldReference))); } - + /** * Creates new {@link RegexMatch} using the result of the provided {@link AggregationExpression} as {@literal input} * value. @@ -1844,10 +1971,12 @@ public static RegexMatch valueOf(String fieldReference) { * @return new instance of {@link RegexMatch}. */ public static RegexMatch valueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexMatch(Collections.singletonMap("input", expression)); } - + /** * Optional specify the options to use with the regular expression. * @@ -1855,54 +1984,82 @@ public static RegexMatch valueOf(AggregationExpression expression) { * @return new instance of {@link RegexMatch}. */ public RegexMatch options(String options) { + Assert.notNull(options, "Options must not be null!"); + return new RegexMatch(append("options", options)); } - + /** - * Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression. + * Optional specify the reference to the {@link Field field} holding the options values to use with the regular + * expression. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexMatch}. */ public RegexMatch optionsOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new RegexMatch(append("options", Fields.field(fieldReference))); } - + /** - * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression. + * Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular + * expression. * * @param expression must not be {@literal null}. * @return new instance of {@link RegexMatch}. */ public RegexMatch optionsOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new RegexMatch(append("options", expression)); } - + /** - * Optional specify the regular expression to apply. + * Apply a {@link Pattern} into {@code regex} and {@code options} fields. + * + * @param pattern must not be {@literal null}. + * @return new instance of {@link RegexMatch}. + */ + public RegexMatch pattern(Pattern pattern) { + + Assert.notNull(pattern, "Pattern must not be null!"); + + Map regex = append("regex", pattern.pattern()); + regex.put("options", RegexFlags.toRegexOptions(pattern.flags())); + + return new RegexMatch(regex); + } + + /** + * Specify the regular expression to apply. * * @param regex must not be {@literal null}. * @return new instance of {@link RegexMatch}. */ public RegexMatch regex(String regex) { + Assert.notNull(regex, "Regex must not be null!"); - return new RegexMatch(append("regex",regex)); + + return new RegexMatch(append("regex", regex)); } - + /** - * Optional specify the reference to the {@link Field field} holding the regular expression to apply. + * Specify the reference to the {@link Field field} holding the regular expression to apply. * * @param fieldReference must not be {@literal null}. * @return new instance of {@link RegexMatch}. */ public RegexMatch regexOf(String fieldReference) { + Assert.notNull(fieldReference, "FieldReference must not be null!"); - return new RegexMatch(append("regex",Fields.field(fieldReference))); + + return new RegexMatch(append("regex", Fields.field(fieldReference))); } - + /** * Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply. * @@ -1910,9 +2067,15 @@ public RegexMatch regexOf(String fieldReference) { * @return new instance of {@link RegexMatch}. */ public RegexMatch regexOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); - return new RegexMatch(append("regex",expression)); + + return new RegexMatch(append("regex", expression)); } + @Override + protected String getMongoMethod() { + return "$regexMatch"; + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 9b1e8df940..f9a354c38f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -42,6 +42,7 @@ import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type; import org.springframework.data.mongodb.core.schema.JsonSchemaProperty; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; +import org.springframework.data.mongodb.util.RegexFlags; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.Base64Utils; @@ -71,20 +72,6 @@ public class Criteria implements CriteriaDefinition { */ private static final Object NOT_SET = new Object(); - private static final int[] FLAG_LOOKUP = new int[Character.MAX_VALUE]; - - static { - FLAG_LOOKUP['g'] = 256; - FLAG_LOOKUP['i'] = Pattern.CASE_INSENSITIVE; - FLAG_LOOKUP['m'] = Pattern.MULTILINE; - FLAG_LOOKUP['s'] = Pattern.DOTALL; - FLAG_LOOKUP['c'] = Pattern.CANON_EQ; - FLAG_LOOKUP['x'] = Pattern.COMMENTS; - FLAG_LOOKUP['d'] = Pattern.UNIX_LINES; - FLAG_LOOKUP['t'] = Pattern.LITERAL; - FLAG_LOOKUP['u'] = Pattern.UNICODE_CASE; - } - private @Nullable String key; private List criteriaChain; private LinkedHashMap criteria = new LinkedHashMap(); @@ -530,7 +517,7 @@ private Pattern toPattern(String regex, @Nullable String options) { Assert.notNull(regex, "Regex string must not be null!"); - return Pattern.compile(regex, regexFlags(options)); + return Pattern.compile(regex, RegexFlags.toRegexFlags(options)); } /** @@ -1099,47 +1086,6 @@ private static boolean requiresGeoJsonFormat(Object value) { || (value instanceof GeoCommand && ((GeoCommand) value).getShape() instanceof GeoJson); } - /** - * Lookup the MongoDB specific flags for a given regex option string. - * - * @param s the Regex option/flag to look up. Can be {@literal null}. - * @return zero if given {@link String} is {@literal null} or empty. - * @since 2.2 - */ - private static int regexFlags(@Nullable String s) { - - int flags = 0; - - if (s == null) { - return flags; - } - - for (final char f : s.toLowerCase().toCharArray()) { - flags |= regexFlag(f); - } - - return flags; - } - - /** - * Lookup the MongoDB specific flags for a given character. - * - * @param c the Regex option/flag to look up. - * @return - * @throws IllegalArgumentException for unknown flags - * @since 2.2 - */ - private static int regexFlag(char c) { - - int flag = FLAG_LOOKUP[c]; - - if (flag == 0) { - throw new IllegalArgumentException(String.format("Unrecognized flag [%c]", c)); - } - - return flag; - } - /** * MongoDB specific bitwise query * operators like {@code $bitsAllClear, $bitsAllSet,...} for usage with {@link Criteria#bits()} and {@link Query}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java new file mode 100644 index 0000000000..dfee94954c --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java @@ -0,0 +1,116 @@ +/* + * Copyright 2021 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 + * + * https://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.util; + +import java.util.regex.Pattern; + +import org.springframework.lang.Nullable; + +/** + * Utility to translate {@link Pattern#flags() regex flags} to MongoDB regex options and vice versa. + * + * @author Mark Paluch + * @since 3.3 + */ +public abstract class RegexFlags { + + private static final int[] FLAG_LOOKUP = new int[Character.MAX_VALUE]; + + static { + FLAG_LOOKUP['g'] = 256; + FLAG_LOOKUP['i'] = Pattern.CASE_INSENSITIVE; + FLAG_LOOKUP['m'] = Pattern.MULTILINE; + FLAG_LOOKUP['s'] = Pattern.DOTALL; + FLAG_LOOKUP['c'] = Pattern.CANON_EQ; + FLAG_LOOKUP['x'] = Pattern.COMMENTS; + FLAG_LOOKUP['d'] = Pattern.UNIX_LINES; + FLAG_LOOKUP['t'] = Pattern.LITERAL; + FLAG_LOOKUP['u'] = Pattern.UNICODE_CASE; + } + + private RegexFlags() { + + } + + /** + * Lookup the MongoDB specific options from given {@link Pattern#flags() flags}. + * + * @param flags the Regex flags to look up. + * @return the options string. May be empty. + */ + public static String toRegexOptions(int flags) { + + if (flags == 0) { + return ""; + } + + StringBuilder buf = new StringBuilder(); + + for (int i = 'a'; i < 'z'; i++) { + + if (FLAG_LOOKUP[i] == 0) { + continue; + } + + if ((flags & FLAG_LOOKUP[i]) > 0) { + buf.append((char) i); + } + } + + return buf.toString(); + } + + /** + * Lookup the MongoDB specific flags for a given regex option string. + * + * @param s the Regex option/flag to look up. Can be {@literal null}. + * @return zero if given {@link String} is {@literal null} or empty. + * @since 2.2 + */ + public static int toRegexFlags(@Nullable String s) { + + int flags = 0; + + if (s == null) { + return flags; + } + + for (char f : s.toLowerCase().toCharArray()) { + flags |= toRegexFlag(f); + } + + return flags; + } + + /** + * Lookup the MongoDB specific flags for a given character. + * + * @param c the Regex option/flag to look up. + * @return + * @throws IllegalArgumentException for unknown flags + * @since 2.2 + */ + public static int toRegexFlag(char c) { + + int flag = FLAG_LOOKUP[c]; + + if (flag == 0) { + throw new IllegalArgumentException(String.format("Unrecognized flag [%c]", c)); + } + + return flag; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java index ff6771d9f1..9ef207c9ad 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java @@ -55,24 +55,25 @@ * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl + * @author Divya Srivastava * @author Mark Paluch */ public class ProjectionOperationUnitTests { - static final String MOD = "$mod"; - static final String ADD = "$add"; - static final String SUBTRACT = "$subtract"; - static final String MULTIPLY = "$multiply"; - static final String DIVIDE = "$divide"; - static final String PROJECT = "$project"; + private static final String MOD = "$mod"; + private static final String ADD = "$add"; + private static final String SUBTRACT = "$subtract"; + private static final String MULTIPLY = "$multiply"; + private static final String DIVIDE = "$divide"; + private static final String PROJECT = "$project"; @Test // DATAMONGO-586 - public void rejectsNullFields() { + void rejectsNullFields() { assertThatIllegalArgumentException().isThrownBy(() -> new ProjectionOperation((Fields) null)); } @Test // DATAMONGO-586 - public void declaresBackReferenceCorrectly() { + void declaresBackReferenceCorrectly() { ProjectionOperation operation = new ProjectionOperation(); operation = operation.and("prop").previousOperation(); @@ -83,7 +84,7 @@ public void declaresBackReferenceCorrectly() { } @Test // DATAMONGO-586 - public void alwaysUsesExplicitReference() { + void alwaysUsesExplicitReference() { ProjectionOperation operation = new ProjectionOperation(Fields.fields("foo").and("bar", "foobar")); @@ -95,7 +96,7 @@ public void alwaysUsesExplicitReference() { } @Test // DATAMONGO-586 - public void aliasesSimpleFieldProjection() { + void aliasesSimpleFieldProjection() { ProjectionOperation operation = new ProjectionOperation(); @@ -106,7 +107,7 @@ public void aliasesSimpleFieldProjection() { } @Test // DATAMONGO-586 - public void aliasesArithmeticProjection() { + void aliasesArithmeticProjection() { ProjectionOperation operation = new ProjectionOperation(); @@ -121,7 +122,7 @@ public void aliasesArithmeticProjection() { } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationWithoutAlias() { + void arithmeticProjectionOperationWithoutAlias() { String fieldName = "a"; ProjectionOperationBuilder operation = new ProjectionOperation().and(fieldName).plus(1); @@ -134,7 +135,7 @@ public void arithmeticProjectionOperationWithoutAlias() { } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationPlus() { + void arithmeticProjectionOperationPlus() { String fieldName = "a"; String fieldAlias = "b"; @@ -148,7 +149,7 @@ public void arithmeticProjectionOperationPlus() { } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationMinus() { + void arithmeticProjectionOperationMinus() { String fieldName = "a"; String fieldAlias = "b"; @@ -162,7 +163,7 @@ public void arithmeticProjectionOperationMinus() { } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationMultiply() { + void arithmeticProjectionOperationMultiply() { String fieldName = "a"; String fieldAlias = "b"; @@ -176,7 +177,7 @@ public void arithmeticProjectionOperationMultiply() { } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationDivide() { + void arithmeticProjectionOperationDivide() { String fieldName = "a"; String fieldAlias = "b"; @@ -190,12 +191,12 @@ public void arithmeticProjectionOperationDivide() { } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationDivideByZeroException() { + void arithmeticProjectionOperationDivideByZeroException() { assertThatIllegalArgumentException().isThrownBy(() -> new ProjectionOperation().and("a").divide(0)); } @Test // DATAMONGO-586 - public void arithmeticProjectionOperationMod() { + void arithmeticProjectionOperationMod() { String fieldName = "a"; String fieldAlias = "b"; @@ -209,7 +210,7 @@ public void arithmeticProjectionOperationMod() { } @Test // DATAMONGO-758, DATAMONGO-1893 - public void excludeShouldAllowExclusionOfFieldsOtherThanUnderscoreId/* since MongoDB 3.4 */() { + void excludeShouldAllowExclusionOfFieldsOtherThanUnderscoreId/* since MongoDB 3.4 */() { ProjectionOperation projectionOp = new ProjectionOperation().andExclude("foo"); Document document = projectionOp.toDocument(Aggregation.DEFAULT_CONTEXT); @@ -220,7 +221,7 @@ public void arithmeticProjectionOperationMod() { } @Test // DATAMONGO-1893 - public void includeShouldNotInheritFields() { + void includeShouldNotInheritFields() { ProjectionOperation projectionOp = new ProjectionOperation().andInclude("foo"); @@ -228,7 +229,7 @@ public void includeShouldNotInheritFields() { } @Test // DATAMONGO-758 - public void excludeShouldAllowExclusionOfUnderscoreId() { + void excludeShouldAllowExclusionOfUnderscoreId() { ProjectionOperation projectionOp = new ProjectionOperation().andExclude(Fields.UNDERSCORE_ID); Document document = projectionOp.toDocument(Aggregation.DEFAULT_CONTEXT); @@ -237,7 +238,7 @@ public void excludeShouldAllowExclusionOfUnderscoreId() { } @Test // DATAMONGO-1906 - public void rendersConditionalProjectionCorrectly() { + void rendersConditionalProjectionCorrectly() { TypedAggregation aggregation = Aggregation.newAggregation(Book.class, Aggregation.project("title") @@ -252,7 +253,7 @@ public void rendersConditionalProjectionCorrectly() { } @Test // DATAMONGO-757 - public void usesImplictAndExplicitFieldAliasAndIncludeExclude() { + void usesImplictAndExplicitFieldAliasAndIncludeExclude() { ProjectionOperation operation = Aggregation.project("foo").and("foobar").as("bar").andInclude("inc1", "inc2") .andExclude("_id"); @@ -268,12 +269,12 @@ public void usesImplictAndExplicitFieldAliasAndIncludeExclude() { } @Test - public void arithmeticProjectionOperationModByZeroException() { + void arithmeticProjectionOperationModByZeroException() { assertThatIllegalArgumentException().isThrownBy(() -> new ProjectionOperation().and("a").mod(0)); } @Test // DATAMONGO-769 - public void allowArithmeticOperationsWithFieldReferences() { + void allowArithmeticOperationsWithFieldReferences() { ProjectionOperation operation = Aggregation.project() // .and("foo").plus("bar").as("fooPlusBar") // @@ -298,7 +299,7 @@ public void allowArithmeticOperationsWithFieldReferences() { } @Test // DATAMONGO-774 - public void projectionExpressions() { + void projectionExpressions() { ProjectionOperation operation = Aggregation.project() // .andExpression("(netPrice + surCharge) * taxrate * [0]", 2).as("grossSalesPrice") // @@ -310,7 +311,7 @@ public void projectionExpressions() { } @Test // DATAMONGO-975 - public void shouldRenderDateTimeFragmentExtractionsForSimpleFieldProjectionsCorrectly() { + void shouldRenderDateTimeFragmentExtractionsForSimpleFieldProjectionsCorrectly() { ProjectionOperation operation = Aggregation.project() // .and("date").extractHour().as("hour") // @@ -343,7 +344,7 @@ public void shouldRenderDateTimeFragmentExtractionsForSimpleFieldProjectionsCorr } @Test // DATAMONGO-975 - public void shouldRenderDateTimeFragmentExtractionsForExpressionProjectionsCorrectly() throws Exception { + void shouldRenderDateTimeFragmentExtractionsForExpressionProjectionsCorrectly() throws Exception { ProjectionOperation operation = Aggregation.project() // .andExpression("date + 86400000") // @@ -360,7 +361,7 @@ public void shouldRenderDateTimeFragmentExtractionsForExpressionProjectionsCorre } @Test // DATAMONGO-979 - public void shouldRenderSizeExpressionInProjection() { + void shouldRenderSizeExpressionInProjection() { ProjectionOperation operation = Aggregation // .project() // @@ -375,7 +376,7 @@ public void shouldRenderSizeExpressionInProjection() { } @Test // DATAMONGO-979 - public void shouldRenderGenericSizeExpressionInProjection() { + void shouldRenderGenericSizeExpressionInProjection() { ProjectionOperation operation = Aggregation // .project() // @@ -389,7 +390,7 @@ public void shouldRenderGenericSizeExpressionInProjection() { } @Test // DATAMONGO-1457 - public void shouldRenderSliceCorrectly() throws Exception { + void shouldRenderSliceCorrectly() throws Exception { ProjectionOperation operation = Aggregation.project().and("field").slice(10).as("renamed"); @@ -400,7 +401,7 @@ public void shouldRenderSliceCorrectly() throws Exception { } @Test // DATAMONGO-1457 - public void shouldRenderSliceWithPositionCorrectly() throws Exception { + void shouldRenderSliceWithPositionCorrectly() throws Exception { ProjectionOperation operation = Aggregation.project().and("field").slice(10, 5).as("renamed"); @@ -411,7 +412,7 @@ public void shouldRenderSliceWithPositionCorrectly() throws Exception { } @Test // DATAMONGO-784 - public void shouldRenderCmpCorrectly() { + void shouldRenderCmpCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").cmp(10).as("cmp10"); @@ -420,7 +421,7 @@ public void shouldRenderCmpCorrectly() { } @Test // DATAMONGO-784 - public void shouldRenderEqCorrectly() { + void shouldRenderEqCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").eq(10).as("eq10"); @@ -429,7 +430,7 @@ public void shouldRenderEqCorrectly() { } @Test // DATAMONGO-784 - public void shouldRenderGtCorrectly() { + void shouldRenderGtCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").gt(10).as("gt10"); @@ -438,7 +439,7 @@ public void shouldRenderGtCorrectly() { } @Test // DATAMONGO-784 - public void shouldRenderGteCorrectly() { + void shouldRenderGteCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").gte(10).as("gte10"); @@ -447,7 +448,7 @@ public void shouldRenderGteCorrectly() { } @Test // DATAMONGO-784 - public void shouldRenderLtCorrectly() { + void shouldRenderLtCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").lt(10).as("lt10"); @@ -456,7 +457,7 @@ public void shouldRenderLtCorrectly() { } @Test // DATAMONGO-784 - public void shouldRenderLteCorrectly() { + void shouldRenderLteCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").lte(10).as("lte10"); @@ -465,7 +466,7 @@ public void shouldRenderLteCorrectly() { } @Test // DATAMONGO-784 - public void shouldRenderNeCorrectly() { + void shouldRenderNeCorrectly() { ProjectionOperation operation = Aggregation.project().and("field").ne(10).as("ne10"); @@ -474,7 +475,7 @@ public void shouldRenderNeCorrectly() { } @Test // DATAMONGO-1536 - public void shouldRenderSetEquals() { + void shouldRenderSetEquals() { Document agg = project("A", "B").and("A").equalsArrays("B").as("sameElements") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -484,7 +485,7 @@ public void shouldRenderSetEquals() { } @Test // DATAMONGO-1536 - public void shouldRenderSetEqualsAggregationExpresssion() { + void shouldRenderSetEqualsAggregationExpresssion() { Document agg = project("A", "B").and(SetOperators.arrayAsSet("A").isEqualTo("B")).as("sameElements") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -494,7 +495,7 @@ public void shouldRenderSetEqualsAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderSetIntersection() { + void shouldRenderSetIntersection() { Document agg = project("A", "B").and("A").intersectsArrays("B").as("commonToBoth") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -504,7 +505,7 @@ public void shouldRenderSetIntersection() { } @Test // DATAMONGO-1536 - public void shouldRenderSetIntersectionAggregationExpresssion() { + void shouldRenderSetIntersectionAggregationExpresssion() { Document agg = project("A", "B").and(SetOperators.arrayAsSet("A").intersects("B")).as("commonToBoth") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -514,7 +515,7 @@ public void shouldRenderSetIntersectionAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderSetUnion() { + void shouldRenderSetUnion() { Document agg = project("A", "B").and("A").unionArrays("B").as("allValues").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -523,7 +524,7 @@ public void shouldRenderSetUnion() { } @Test // DATAMONGO-1536 - public void shouldRenderSetUnionAggregationExpresssion() { + void shouldRenderSetUnionAggregationExpresssion() { Document agg = project("A", "B").and(SetOperators.arrayAsSet("A").union("B")).as("allValues") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -533,7 +534,7 @@ public void shouldRenderSetUnionAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderSetDifference() { + void shouldRenderSetDifference() { Document agg = project("A", "B").and("B").differenceToArray("A").as("inBOnly") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -543,7 +544,7 @@ public void shouldRenderSetDifference() { } @Test // DATAMONGO-1536 - public void shouldRenderSetDifferenceAggregationExpresssion() { + void shouldRenderSetDifferenceAggregationExpresssion() { Document agg = project("A", "B").and(SetOperators.arrayAsSet("B").differenceTo("A")).as("inBOnly") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -553,7 +554,7 @@ public void shouldRenderSetDifferenceAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderSetIsSubset() { + void shouldRenderSetIsSubset() { Document agg = project("A", "B").and("A").subsetOfArray("B").as("aIsSubsetOfB") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -563,7 +564,7 @@ public void shouldRenderSetIsSubset() { } @Test // DATAMONGO-1536 - public void shouldRenderSetIsSubsetAggregationExpresssion() { + void shouldRenderSetIsSubsetAggregationExpresssion() { Document agg = project("A", "B").and(SetOperators.arrayAsSet("A").isSubsetOf("B")).as("aIsSubsetOfB") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -573,7 +574,7 @@ public void shouldRenderSetIsSubsetAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderAnyElementTrue() { + void shouldRenderAnyElementTrue() { Document agg = project("responses").and("responses").anyElementInArrayTrue().as("isAnyTrue") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -583,7 +584,7 @@ public void shouldRenderAnyElementTrue() { } @Test // DATAMONGO-1536 - public void shouldRenderAnyElementTrueAggregationExpresssion() { + void shouldRenderAnyElementTrueAggregationExpresssion() { Document agg = project("responses").and(SetOperators.arrayAsSet("responses").anyElementTrue()).as("isAnyTrue") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -593,7 +594,7 @@ public void shouldRenderAnyElementTrueAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderAllElementsTrue() { + void shouldRenderAllElementsTrue() { Document agg = project("responses").and("responses").allElementsInArrayTrue().as("isAllTrue") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -603,7 +604,7 @@ public void shouldRenderAllElementsTrue() { } @Test // DATAMONGO-1536 - public void shouldRenderAllElementsTrueAggregationExpresssion() { + void shouldRenderAllElementsTrueAggregationExpresssion() { Document agg = project("responses").and(SetOperators.arrayAsSet("responses").allElementsTrue()).as("isAllTrue") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -613,7 +614,7 @@ public void shouldRenderAllElementsTrueAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderAbs() { + void shouldRenderAbs() { Document agg = project().and("anyNumber").absoluteValue().as("absoluteValue") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -622,7 +623,7 @@ public void shouldRenderAbs() { } @Test // DATAMONGO-1536 - public void shouldRenderAbsAggregationExpresssion() { + void shouldRenderAbsAggregationExpresssion() { Document agg = project() .and( @@ -634,7 +635,7 @@ public void shouldRenderAbsAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderAddAggregationExpresssion() { + void shouldRenderAddAggregationExpresssion() { Document agg = project().and(ArithmeticOperators.valueOf("price").add("fee")).as("total") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -643,7 +644,7 @@ public void shouldRenderAddAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderCeil() { + void shouldRenderCeil() { Document agg = project().and("anyNumber").ceil().as("ceilValue").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -651,7 +652,7 @@ public void shouldRenderCeil() { } @Test // DATAMONGO-1536 - public void shouldRenderCeilAggregationExpresssion() { + void shouldRenderCeilAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).ceil()) @@ -662,7 +663,7 @@ public void shouldRenderCeilAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderDivide() { + void shouldRenderDivide() { Document agg = project().and("value") .divide(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).as("result") @@ -673,7 +674,7 @@ public void shouldRenderDivide() { } @Test // DATAMONGO-1536 - public void shouldRenderDivideAggregationExpresssion() { + void shouldRenderDivideAggregationExpresssion() { Document agg = project() .and(ArithmeticOperators.valueOf("anyNumber") @@ -685,7 +686,7 @@ public void shouldRenderDivideAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderExp() { + void shouldRenderExp() { Document agg = project().and("value").exp().as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -693,7 +694,7 @@ public void shouldRenderExp() { } @Test // DATAMONGO-1536 - public void shouldRenderExpAggregationExpresssion() { + void shouldRenderExpAggregationExpresssion() { Document agg = project() .and( @@ -705,7 +706,7 @@ public void shouldRenderExpAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderFloor() { + void shouldRenderFloor() { Document agg = project().and("value").floor().as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -713,7 +714,7 @@ public void shouldRenderFloor() { } @Test // DATAMONGO-1536 - public void shouldRenderFloorAggregationExpresssion() { + void shouldRenderFloorAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).floor()) @@ -724,7 +725,7 @@ public void shouldRenderFloorAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderLn() { + void shouldRenderLn() { Document agg = project().and("value").ln().as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -732,7 +733,7 @@ public void shouldRenderLn() { } @Test // DATAMONGO-1536 - public void shouldRenderLnAggregationExpresssion() { + void shouldRenderLnAggregationExpresssion() { Document agg = project() .and(ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).ln()) @@ -743,7 +744,7 @@ public void shouldRenderLnAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderLog() { + void shouldRenderLog() { Document agg = project().and("value").log(2).as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -751,7 +752,7 @@ public void shouldRenderLog() { } @Test // DATAMONGO-1536 - public void shouldRenderLogAggregationExpresssion() { + void shouldRenderLogAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).log(2)) @@ -762,7 +763,7 @@ public void shouldRenderLogAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderLog10() { + void shouldRenderLog10() { Document agg = project().and("value").log10().as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -770,7 +771,7 @@ public void shouldRenderLog10() { } @Test // DATAMONGO-1536 - public void shouldRenderLog10AggregationExpresssion() { + void shouldRenderLog10AggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).log10()) @@ -781,7 +782,7 @@ public void shouldRenderLog10AggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderMod() { + void shouldRenderMod() { Document agg = project().and("value").mod(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))) .as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -791,7 +792,7 @@ public void shouldRenderMod() { } @Test // DATAMONGO-1536 - public void shouldRenderModAggregationExpresssion() { + void shouldRenderModAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).mod(2)) @@ -802,7 +803,7 @@ public void shouldRenderModAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderMultiply() { + void shouldRenderMultiply() { Document agg = project().and("value") .multiply(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).as("result") @@ -813,7 +814,7 @@ public void shouldRenderMultiply() { } @Test // DATAMONGO-1536 - public void shouldRenderMultiplyAggregationExpresssion() { + void shouldRenderMultiplyAggregationExpresssion() { Document agg = project() .and(ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))) @@ -825,7 +826,7 @@ public void shouldRenderMultiplyAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderPow() { + void shouldRenderPow() { Document agg = project().and("value").pow(2).as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -833,7 +834,7 @@ public void shouldRenderPow() { } @Test // DATAMONGO-1536 - public void shouldRenderPowAggregationExpresssion() { + void shouldRenderPowAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).pow(2)) @@ -844,7 +845,7 @@ public void shouldRenderPowAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderSqrt() { + void shouldRenderSqrt() { Document agg = project().and("value").sqrt().as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -852,7 +853,7 @@ public void shouldRenderSqrt() { } @Test // DATAMONGO-1536 - public void shouldRenderSqrtAggregationExpresssion() { + void shouldRenderSqrtAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).sqrt()) @@ -863,7 +864,7 @@ public void shouldRenderSqrtAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderSubtract() { + void shouldRenderSubtract() { Document agg = project().and("numericField").minus(AggregationFunctionExpressions.SIZE.of(field("someArray"))) .as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -873,7 +874,7 @@ public void shouldRenderSubtract() { } @Test // DATAMONGO-1536 - public void shouldRenderSubtractAggregationExpresssion() { + void shouldRenderSubtractAggregationExpresssion() { Document agg = project() .and(ArithmeticOperators.valueOf("numericField") @@ -885,7 +886,7 @@ public void shouldRenderSubtractAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderTrunc() { + void shouldRenderTrunc() { Document agg = project().and("value").trunc().as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -893,7 +894,7 @@ public void shouldRenderTrunc() { } @Test // DATAMONGO-1536 - public void shouldRenderTruncAggregationExpresssion() { + void shouldRenderTruncAggregationExpresssion() { Document agg = project().and( ArithmeticOperators.valueOf(AggregationFunctionExpressions.SUBTRACT.of(field("start"), field("end"))).trunc()) @@ -904,7 +905,7 @@ public void shouldRenderTruncAggregationExpresssion() { } @Test // DATAMONGO-1536 - public void shouldRenderConcat() { + void shouldRenderConcat() { Document agg = project().and("item").concat(" - ", field("description")).as("itemDescription") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -915,7 +916,7 @@ public void shouldRenderConcat() { } @Test // DATAMONGO-1536 - public void shouldRenderConcatAggregationExpression() { + void shouldRenderConcatAggregationExpression() { Document agg = project().and(StringOperators.valueOf("item").concat(" - ").concatValueOf("description")) .as("itemDescription").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -926,7 +927,7 @@ public void shouldRenderConcatAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderSubstr() { + void shouldRenderSubstr() { Document agg = project().and("quarter").substring(0, 2).as("yearSubstring").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -934,7 +935,7 @@ public void shouldRenderSubstr() { } @Test // DATAMONGO-1536 - public void shouldRenderSubstrAggregationExpression() { + void shouldRenderSubstrAggregationExpression() { Document agg = project().and(StringOperators.valueOf("quarter").substring(0, 2)).as("yearSubstring") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -943,7 +944,7 @@ public void shouldRenderSubstrAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderToLower() { + void shouldRenderToLower() { Document agg = project().and("item").toLower().as("item").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -951,7 +952,7 @@ public void shouldRenderToLower() { } @Test // DATAMONGO-1536 - public void shouldRenderToLowerAggregationExpression() { + void shouldRenderToLowerAggregationExpression() { Document agg = project().and(StringOperators.valueOf("item").toLower()).as("item") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -960,7 +961,7 @@ public void shouldRenderToLowerAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderToUpper() { + void shouldRenderToUpper() { Document agg = project().and("item").toUpper().as("item").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -968,7 +969,7 @@ public void shouldRenderToUpper() { } @Test // DATAMONGO-1536 - public void shouldRenderToUpperAggregationExpression() { + void shouldRenderToUpperAggregationExpression() { Document agg = project().and(StringOperators.valueOf("item").toUpper()).as("item") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -977,7 +978,7 @@ public void shouldRenderToUpperAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderStrCaseCmp() { + void shouldRenderStrCaseCmp() { Document agg = project().and("quarter").strCaseCmp("13q4").as("comparisonResult") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -987,7 +988,7 @@ public void shouldRenderStrCaseCmp() { } @Test // DATAMONGO-1536 - public void shouldRenderStrCaseCmpAggregationExpression() { + void shouldRenderStrCaseCmpAggregationExpression() { Document agg = project().and(StringOperators.valueOf("quarter").strCaseCmp("13q4")).as("comparisonResult") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -997,7 +998,7 @@ public void shouldRenderStrCaseCmpAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderArrayElementAt() { + void shouldRenderArrayElementAt() { Document agg = project().and("favorites").arrayElementAt(0).as("first").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1005,7 +1006,7 @@ public void shouldRenderArrayElementAt() { } @Test // DATAMONGO-1536 - public void shouldRenderArrayElementAtAggregationExpression() { + void shouldRenderArrayElementAtAggregationExpression() { Document agg = project().and(ArrayOperators.arrayOf("favorites").elementAt(0)).as("first") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1014,7 +1015,7 @@ public void shouldRenderArrayElementAtAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderConcatArrays() { + void shouldRenderConcatArrays() { Document agg = project().and("instock").concatArrays("ordered").as("items").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1023,7 +1024,7 @@ public void shouldRenderConcatArrays() { } @Test // DATAMONGO-1536 - public void shouldRenderConcatArraysAggregationExpression() { + void shouldRenderConcatArraysAggregationExpression() { Document agg = project().and(ArrayOperators.arrayOf("instock").concat("ordered")).as("items") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1033,7 +1034,7 @@ public void shouldRenderConcatArraysAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderIsArray() { + void shouldRenderIsArray() { Document agg = project().and("instock").isArray().as("isAnArray").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1041,7 +1042,7 @@ public void shouldRenderIsArray() { } @Test // DATAMONGO-1536 - public void shouldRenderIsArrayAggregationExpression() { + void shouldRenderIsArrayAggregationExpression() { Document agg = project().and(ArrayOperators.arrayOf("instock").isArray()).as("isAnArray") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1050,7 +1051,7 @@ public void shouldRenderIsArrayAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderSizeAggregationExpression() { + void shouldRenderSizeAggregationExpression() { Document agg = project().and(ArrayOperators.arrayOf("instock").length()).as("arraySize") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1059,7 +1060,7 @@ public void shouldRenderSizeAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderSliceAggregationExpression() { + void shouldRenderSliceAggregationExpression() { Document agg = project().and(ArrayOperators.arrayOf("favorites").slice().itemCount(3)).as("threeFavorites") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1068,7 +1069,7 @@ public void shouldRenderSliceAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderSliceWithPositionAggregationExpression() { + void shouldRenderSliceWithPositionAggregationExpression() { Document agg = project().and(ArrayOperators.arrayOf("favorites").slice().offset(2).itemCount(3)) .as("threeFavorites").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1077,7 +1078,7 @@ public void shouldRenderSliceWithPositionAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderLiteral() { + void shouldRenderLiteral() { Document agg = project().and("$1").asLiteral().as("literalOnly").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1085,7 +1086,7 @@ public void shouldRenderLiteral() { } @Test // DATAMONGO-1536 - public void shouldRenderLiteralAggregationExpression() { + void shouldRenderLiteralAggregationExpression() { Document agg = project().and(LiteralOperators.valueOf("$1").asLiteral()).as("literalOnly") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1094,7 +1095,7 @@ public void shouldRenderLiteralAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderDayOfYearAggregationExpression() { + void shouldRenderDayOfYearAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").dayOfYear()).as("dayOfYear") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1103,7 +1104,7 @@ public void shouldRenderDayOfYearAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderDayOfYearAggregationExpressionWithTimezone() { + void shouldRenderDayOfYearAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).dayOfYear()).as("dayOfYear") @@ -1114,7 +1115,7 @@ public void shouldRenderDayOfYearAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1834 - public void shouldRenderTimeZoneFromField() { + void shouldRenderTimeZoneFromField() { Document agg = project().and(DateOperators.dateOf("date").withTimezone(Timezone.ofField("tz")).dayOfYear()) .as("dayOfYear").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1124,7 +1125,7 @@ public void shouldRenderTimeZoneFromField() { } @Test // DATAMONGO-1834 - public void shouldRenderTimeZoneFromExpression() { + void shouldRenderTimeZoneFromExpression() { Document agg = project() .and(DateOperators.dateOf("date") @@ -1136,7 +1137,7 @@ public void shouldRenderTimeZoneFromExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderDayOfMonthAggregationExpression() { + void shouldRenderDayOfMonthAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").dayOfMonth()).as("day") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1145,7 +1146,7 @@ public void shouldRenderDayOfMonthAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderDayOfMonthAggregationExpressionWithTimezone() { + void shouldRenderDayOfMonthAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).dayOfMonth()).as("day") @@ -1156,7 +1157,7 @@ public void shouldRenderDayOfMonthAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderDayOfWeekAggregationExpression() { + void shouldRenderDayOfWeekAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").dayOfWeek()).as("dayOfWeek") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1165,7 +1166,7 @@ public void shouldRenderDayOfWeekAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderDayOfWeekAggregationExpressionWithTimezone() { + void shouldRenderDayOfWeekAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).dayOfWeek()).as("dayOfWeek") @@ -1176,7 +1177,7 @@ public void shouldRenderDayOfWeekAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderYearAggregationExpression() { + void shouldRenderYearAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").year()).as("year") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1185,7 +1186,7 @@ public void shouldRenderYearAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderYearAggregationExpressionWithTimezone() { + void shouldRenderYearAggregationExpressionWithTimezone() { Document agg = project().and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).year()) .as("year").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1195,7 +1196,7 @@ public void shouldRenderYearAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderMonthAggregationExpression() { + void shouldRenderMonthAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").month()).as("month") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1204,7 +1205,7 @@ public void shouldRenderMonthAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderMonthAggregationExpressionWithTimezone() { + void shouldRenderMonthAggregationExpressionWithTimezone() { Document agg = project().and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).month()) .as("month").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1214,7 +1215,7 @@ public void shouldRenderMonthAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderWeekAggregationExpression() { + void shouldRenderWeekAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").week()).as("week") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1223,7 +1224,7 @@ public void shouldRenderWeekAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderWeekAggregationExpressionWithTimezone() { + void shouldRenderWeekAggregationExpressionWithTimezone() { Document agg = project().and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).week()) .as("week").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1233,7 +1234,7 @@ public void shouldRenderWeekAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderHourAggregationExpression() { + void shouldRenderHourAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").hour()).as("hour") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1242,7 +1243,7 @@ public void shouldRenderHourAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderHourAggregationExpressionWithTimezone() { + void shouldRenderHourAggregationExpressionWithTimezone() { Document agg = project().and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).hour()) .as("hour").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1252,7 +1253,7 @@ public void shouldRenderHourAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderMinuteAggregationExpression() { + void shouldRenderMinuteAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").minute()).as("minute") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1261,7 +1262,7 @@ public void shouldRenderMinuteAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderMinuteAggregationExpressionWithTimezone() { + void shouldRenderMinuteAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).minute()).as("minute") @@ -1272,7 +1273,7 @@ public void shouldRenderMinuteAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderSecondAggregationExpression() { + void shouldRenderSecondAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").second()).as("second") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1281,7 +1282,7 @@ public void shouldRenderSecondAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderSecondAggregationExpressionWithTimezone() { + void shouldRenderSecondAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).second()).as("second") @@ -1292,7 +1293,7 @@ public void shouldRenderSecondAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderMillisecondAggregationExpression() { + void shouldRenderMillisecondAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").millisecond()).as("msec") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1301,7 +1302,7 @@ public void shouldRenderMillisecondAggregationExpression() { } @Test // DATAMONGO-1834 - public void shouldRenderMillisecondAggregationExpressionWithTimezone() { + void shouldRenderMillisecondAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).millisecond()).as("msec") @@ -1312,7 +1313,7 @@ public void shouldRenderMillisecondAggregationExpressionWithTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderDateToString() { + void shouldRenderDateToString() { Document agg = project().and("date").dateAsFormattedString("%H:%M:%S:%L").as("time") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1322,7 +1323,7 @@ public void shouldRenderDateToString() { } @Test // DATAMONGO-2047 - public void shouldRenderDateToStringWithoutFormatOption() { + void shouldRenderDateToStringWithoutFormatOption() { Document agg = project().and("date").dateAsFormattedString().as("time").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1330,7 +1331,7 @@ public void shouldRenderDateToStringWithoutFormatOption() { } @Test // DATAMONGO-1536 - public void shouldRenderDateToStringAggregationExpression() { + void shouldRenderDateToStringAggregationExpression() { Document agg = project().and(DateOperators.dateOf("date").toString("%H:%M:%S:%L")).as("time") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1340,7 +1341,7 @@ public void shouldRenderDateToStringAggregationExpression() { } @Test // DATAMONGO-1834, DATAMONGO-2047 - public void shouldRenderDateToStringAggregationExpressionWithTimezone() { + void shouldRenderDateToStringAggregationExpressionWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).toString("%H:%M:%S:%L")) @@ -1358,7 +1359,7 @@ public void shouldRenderDateToStringAggregationExpressionWithTimezone() { } @Test // DATAMONGO-2047 - public void shouldRenderDateToStringWithOnNull() { + void shouldRenderDateToStringWithOnNull() { Document agg = project() .and(DateOperators.dateOf("date").toStringWithDefaultFormat().onNullReturnValueOf("fallback-field")).as("time") @@ -1369,7 +1370,7 @@ public void shouldRenderDateToStringWithOnNull() { } @Test // DATAMONGO-2047 - public void shouldRenderDateToStringWithOnNullExpression() { + void shouldRenderDateToStringWithOnNullExpression() { Document agg = project() .and(DateOperators.dateOf("date").toStringWithDefaultFormat() @@ -1381,7 +1382,7 @@ public void shouldRenderDateToStringWithOnNullExpression() { } @Test // DATAMONGO-2047 - public void shouldRenderDateToStringWithOnNullAndTimezone() { + void shouldRenderDateToStringWithOnNullAndTimezone() { Document agg = project().and(DateOperators.dateOf("date").toStringWithDefaultFormat() .onNullReturnValueOf("fallback-field").withTimezone(Timezone.ofField("foo"))).as("time") @@ -1392,7 +1393,7 @@ public void shouldRenderDateToStringWithOnNullAndTimezone() { } @Test // DATAMONGO-1536 - public void shouldRenderSumAggregationExpression() { + void shouldRenderSumAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("quizzes").sum()).as("quizTotal") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1401,7 +1402,7 @@ public void shouldRenderSumAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderSumWithMultipleArgsAggregationExpression() { + void shouldRenderSumWithMultipleArgsAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("final").sum().and("midterm")).as("examTotal") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1410,7 +1411,7 @@ public void shouldRenderSumWithMultipleArgsAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderAvgAggregationExpression() { + void shouldRenderAvgAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("quizzes").avg()).as("quizAvg") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1419,7 +1420,7 @@ public void shouldRenderAvgAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderAvgWithMultipleArgsAggregationExpression() { + void shouldRenderAvgWithMultipleArgsAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("final").avg().and("midterm")).as("examAvg") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1428,7 +1429,7 @@ public void shouldRenderAvgWithMultipleArgsAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderMaxAggregationExpression() { + void shouldRenderMaxAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("quizzes").max()).as("quizMax") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1437,7 +1438,7 @@ public void shouldRenderMaxAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderMaxWithMultipleArgsAggregationExpression() { + void shouldRenderMaxWithMultipleArgsAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("final").max().and("midterm")).as("examMax") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1446,7 +1447,7 @@ public void shouldRenderMaxWithMultipleArgsAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderMinAggregationExpression() { + void shouldRenderMinAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("quizzes").min()).as("quizMin") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1455,7 +1456,7 @@ public void shouldRenderMinAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderMinWithMultipleArgsAggregationExpression() { + void shouldRenderMinWithMultipleArgsAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("final").min().and("midterm")).as("examMin") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1464,7 +1465,7 @@ public void shouldRenderMinWithMultipleArgsAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderStdDevPopAggregationExpression() { + void shouldRenderStdDevPopAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("scores").stdDevPop()).as("stdDev") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1473,7 +1474,7 @@ public void shouldRenderStdDevPopAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderStdDevSampAggregationExpression() { + void shouldRenderStdDevSampAggregationExpression() { Document agg = project().and(ArithmeticOperators.valueOf("scores").stdDevSamp()).as("stdDev") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1482,7 +1483,7 @@ public void shouldRenderStdDevSampAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderCmpAggregationExpression() { + void shouldRenderCmpAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").compareToValue(250)).as("cmp250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1491,7 +1492,7 @@ public void shouldRenderCmpAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderEqAggregationExpression() { + void shouldRenderEqAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").equalToValue(250)).as("eq250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1500,7 +1501,7 @@ public void shouldRenderEqAggregationExpression() { } @Test // DATAMONGO-2513 - public void shouldRenderEqAggregationExpressionWithListComparison() { + void shouldRenderEqAggregationExpressionWithListComparison() { Document agg = project().and(ComparisonOperators.valueOf("qty").equalToValue(Arrays.asList(250))).as("eq250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1509,7 +1510,7 @@ public void shouldRenderEqAggregationExpressionWithListComparison() { } @Test // DATAMONGO-1536 - public void shouldRenderGtAggregationExpression() { + void shouldRenderGtAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").greaterThanValue(250)).as("gt250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1518,7 +1519,7 @@ public void shouldRenderGtAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderGteAggregationExpression() { + void shouldRenderGteAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").greaterThanEqualToValue(250)).as("gte250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1527,7 +1528,7 @@ public void shouldRenderGteAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderLtAggregationExpression() { + void shouldRenderLtAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").lessThanValue(250)).as("lt250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1536,7 +1537,7 @@ public void shouldRenderLtAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderLteAggregationExpression() { + void shouldRenderLteAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").lessThanEqualToValue(250)).as("lte250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1545,7 +1546,7 @@ public void shouldRenderLteAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderNeAggregationExpression() { + void shouldRenderNeAggregationExpression() { Document agg = project().and(ComparisonOperators.valueOf("qty").notEqualToValue(250)).as("ne250") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1554,7 +1555,7 @@ public void shouldRenderNeAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderLogicAndAggregationExpression() { + void shouldRenderLogicAndAggregationExpression() { Document agg = project() .and(BooleanOperators.valueOf(ComparisonOperators.valueOf("qty").greaterThanValue(100)) @@ -1566,7 +1567,7 @@ public void shouldRenderLogicAndAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderLogicOrAggregationExpression() { + void shouldRenderLogicOrAggregationExpression() { Document agg = project() .and(BooleanOperators.valueOf(ComparisonOperators.valueOf("qty").greaterThanValue(250)) @@ -1578,7 +1579,7 @@ public void shouldRenderLogicOrAggregationExpression() { } @Test // DATAMONGO-1536 - public void shouldRenderNotAggregationExpression() { + void shouldRenderNotAggregationExpression() { Document agg = project().and(BooleanOperators.not(ComparisonOperators.valueOf("qty").greaterThanValue(250))) .as("result").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1587,7 +1588,7 @@ public void shouldRenderNotAggregationExpression() { } @Test // DATAMONGO-1540 - public void shouldRenderMapAggregationExpression() { + void shouldRenderMapAggregationExpression() { Document agg = Aggregation.project() .and(VariableOperators.mapItemsOf("quizzes").as("grade") @@ -1599,7 +1600,7 @@ public void shouldRenderMapAggregationExpression() { } @Test // DATAMONGO-1540 - public void shouldRenderMapAggregationExpressionOnExpression() { + void shouldRenderMapAggregationExpressionOnExpression() { Document agg = Aggregation.project() .and(VariableOperators.mapItemsOf(AggregationFunctionExpressions.SIZE.of("foo")).as("grade") @@ -1611,7 +1612,7 @@ public void shouldRenderMapAggregationExpressionOnExpression() { } @Test // DATAMONGO-861, DATAMONGO-1542 - public void shouldRenderIfNullConditionAggregationExpression() { + void shouldRenderIfNullConditionAggregationExpression() { Document agg = project().and( ConditionalOperators.ifNull(ArrayOperators.arrayOf("array").elementAt(1)).then("a more sophisticated value")) @@ -1622,7 +1623,7 @@ public void shouldRenderIfNullConditionAggregationExpression() { } @Test // DATAMONGO-1542 - public void shouldRenderIfNullValueAggregationExpression() { + void shouldRenderIfNullValueAggregationExpression() { Document agg = project() .and(ConditionalOperators.ifNull("field").then(ArrayOperators.arrayOf("array").elementAt(1))).as("result") @@ -1633,7 +1634,7 @@ public void shouldRenderIfNullValueAggregationExpression() { } @Test // DATAMONGO-861, DATAMONGO-1542 - public void fieldReplacementIfNullShouldRenderCorrectly() { + void fieldReplacementIfNullShouldRenderCorrectly() { Document agg = project().and(ConditionalOperators.ifNull("optional").thenValueOf("$never-null")).as("result") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1643,7 +1644,7 @@ public void fieldReplacementIfNullShouldRenderCorrectly() { } @Test // DATAMONGO-1538 - public void shouldRenderLetExpressionCorrectly() { + void shouldRenderLetExpressionCorrectly() { Document agg = Aggregation.project() .and(VariableOperators @@ -1665,7 +1666,7 @@ public void shouldRenderLetExpressionCorrectly() { } @Test // DATAMONGO-1538 - public void shouldRenderLetExpressionCorrectlyWhenUsingLetOnProjectionBuilder() { + void shouldRenderLetExpressionCorrectlyWhenUsingLetOnProjectionBuilder() { ExpressionVariable var1 = newVariable("total") .forExpression(AggregationFunctionExpressions.ADD.of(Fields.field("price"), Fields.field("tax"))); @@ -1688,7 +1689,7 @@ public void shouldRenderLetExpressionCorrectlyWhenUsingLetOnProjectionBuilder() } @Test // DATAMONGO-1548 - public void shouldRenderIndexOfBytesCorrectly() { + void shouldRenderIndexOfBytesCorrectly() { Document agg = project().and(StringOperators.valueOf("item").indexOf("foo")).as("byteLocation") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1698,7 +1699,7 @@ public void shouldRenderIndexOfBytesCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIndexOfBytesWithRangeCorrectly() { + void shouldRenderIndexOfBytesWithRangeCorrectly() { Document agg = project() .and(StringOperators.valueOf("item").indexOf("foo") @@ -1710,7 +1711,7 @@ public void shouldRenderIndexOfBytesWithRangeCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIndexOfCPCorrectly() { + void shouldRenderIndexOfCPCorrectly() { Document agg = project().and(StringOperators.valueOf("item").indexOfCP("foo")).as("cpLocation") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1719,7 +1720,7 @@ public void shouldRenderIndexOfCPCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIndexOfCPWithRangeCorrectly() { + void shouldRenderIndexOfCPWithRangeCorrectly() { Document agg = project() .and(StringOperators.valueOf("item").indexOfCP("foo") @@ -1731,7 +1732,7 @@ public void shouldRenderIndexOfCPWithRangeCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderSplitCorrectly() { + void shouldRenderSplitCorrectly() { Document agg = project().and(StringOperators.valueOf("city").split(", ")).as("city_state") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1740,7 +1741,7 @@ public void shouldRenderSplitCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderStrLenBytesCorrectly() { + void shouldRenderStrLenBytesCorrectly() { Document agg = project().and(StringOperators.valueOf("name").length()).as("length") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1749,7 +1750,7 @@ public void shouldRenderStrLenBytesCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderStrLenCPCorrectly() { + void shouldRenderStrLenCPCorrectly() { Document agg = project().and(StringOperators.valueOf("name").lengthCP()).as("length") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1758,7 +1759,7 @@ public void shouldRenderStrLenCPCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderSubstrCPCorrectly() { + void shouldRenderSubstrCPCorrectly() { Document agg = project().and(StringOperators.valueOf("quarter").substringCP(0, 2)).as("yearSubstring") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1766,27 +1767,27 @@ public void shouldRenderSubstrCPCorrectly() { assertThat(agg) .isEqualTo(Document.parse("{ $project : { yearSubstring: { $substrCP: [ \"$quarter\", 0, 2 ] } } }")); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindCorrectly() { + + @Test // GH-3725 + void shouldRenderRegexFindCorrectly() { Document agg = project().and(StringOperators.valueOf("field1").regexFind("e")).as("regex") .toDocument(Aggregation.DEFAULT_CONTEXT); assertThat(agg).isEqualTo(Document.parse("{ $project : { regex: { $regexFind: { \"input\" : \"$field1\", \"regex\" : \"e\" } } } }")); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindAllCorrectly() { + + @Test // GH-3725 + void shouldRenderRegexFindAllCorrectly() { Document agg = project().and(StringOperators.valueOf("field1").regexFindAll("e")).as("regex") .toDocument(Aggregation.DEFAULT_CONTEXT); assertThat(agg).isEqualTo(Document.parse("{ $project : { regex: { $regexFindAll: { \"input\" : \"$field1\", \"regex\" : \"e\" } } } }")); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexMatchCorrectly() { + + @Test // GH-3725 + void shouldRenderRegexMatchCorrectly() { Document agg = project().and(StringOperators.valueOf("field1").regexMatch("e")).as("regex") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1795,7 +1796,7 @@ public void shouldRenderRegexMatchCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIndexOfArrayCorrectly() { + void shouldRenderIndexOfArrayCorrectly() { Document agg = project().and(ArrayOperators.arrayOf("items").indexOf(2)).as("index") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1804,7 +1805,7 @@ public void shouldRenderIndexOfArrayCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderRangeCorrectly() { + void shouldRenderRangeCorrectly() { Document agg = project().and(ArrayOperators.RangeOperator.rangeStartingAt(0L).to("distance").withStepSize(25L)) .as("rest_stops").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1815,7 +1816,7 @@ public void shouldRenderRangeCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderReverseArrayCorrectly() { + void shouldRenderReverseArrayCorrectly() { Document agg = project().and(ArrayOperators.arrayOf("favorites").reverse()).as("reverseFavorites") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1824,7 +1825,7 @@ public void shouldRenderReverseArrayCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderReduceWithSimpleObjectCorrectly() { + void shouldRenderReduceWithSimpleObjectCorrectly() { Document agg = project() .and(ArrayOperators.arrayOf("probabilityArr") @@ -1836,7 +1837,7 @@ public void shouldRenderReduceWithSimpleObjectCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderReduceWithComplexObjectCorrectly() { + void shouldRenderReduceWithComplexObjectCorrectly() { PropertyExpression sum = PropertyExpression.property("sum").definedAs( ArithmeticOperators.valueOf(Variable.VALUE.referringTo("sum").getName()).add(Variable.THIS.getName())); @@ -1853,7 +1854,7 @@ public void shouldRenderReduceWithComplexObjectCorrectly() { } @Test // DATAMONGO-1843 - public void shouldRenderReduceWithInputAndInExpressionsCorrectly() { + void shouldRenderReduceWithInputAndInExpressionsCorrectly() { Document expected = Document.parse( "{ \"$project\" : { \"results\" : { \"$reduce\" : { \"input\" : { \"$slice\" : [\"$array\", 5] }, \"initialValue\" : \"\", \"in\" : { \"$concat\" : [\"$$value\", \"/\", \"$$this\"] } } } } }"); @@ -1874,7 +1875,7 @@ public void shouldRenderReduceWithInputAndInExpressionsCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderZipCorrectly() { + void shouldRenderZipCorrectly() { AggregationExpression elemAt0 = ArrayOperators.arrayOf("matrix").elementAt(0); AggregationExpression elemAt1 = ArrayOperators.arrayOf("matrix").elementAt(1); @@ -1889,7 +1890,7 @@ public void shouldRenderZipCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderInCorrectly() { + void shouldRenderInCorrectly() { Document agg = project().and(ArrayOperators.arrayOf("in_stock").containsValue("bananas")).as("has_bananas") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1899,7 +1900,7 @@ public void shouldRenderInCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIsoDayOfWeekCorrectly() { + void shouldRenderIsoDayOfWeekCorrectly() { Document agg = project().and(DateOperators.dateOf("birthday").isoDayOfWeek()).as("dayOfWeek") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1908,7 +1909,7 @@ public void shouldRenderIsoDayOfWeekCorrectly() { } @Test // DATAMONGO-1834 - public void shouldRenderIsoDayOfWeekWithTimezoneCorrectly() { + void shouldRenderIsoDayOfWeekWithTimezoneCorrectly() { Document agg = project() .and(DateOperators.dateOf("birthday").withTimezone(Timezone.valueOf("America/Chicago")).isoDayOfWeek()) @@ -1919,7 +1920,7 @@ public void shouldRenderIsoDayOfWeekWithTimezoneCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIsoWeekCorrectly() { + void shouldRenderIsoWeekCorrectly() { Document agg = project().and(DateOperators.dateOf("date").isoWeek()).as("weekNumber") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1928,7 +1929,7 @@ public void shouldRenderIsoWeekCorrectly() { } @Test // DATAMONGO-1834 - public void shouldRenderIsoWeekWithTimezoneCorrectly() { + void shouldRenderIsoWeekWithTimezoneCorrectly() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).isoWeek()).as("weekNumber") @@ -1939,7 +1940,7 @@ public void shouldRenderIsoWeekWithTimezoneCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderIsoWeekYearCorrectly() { + void shouldRenderIsoWeekYearCorrectly() { Document agg = project().and(DateOperators.dateOf("date").isoWeekYear()).as("yearNumber") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -1948,7 +1949,7 @@ public void shouldRenderIsoWeekYearCorrectly() { } @Test // DATAMONGO-1834 - public void shouldRenderIsoWeekYearWithTimezoneCorrectly() { + void shouldRenderIsoWeekYearWithTimezoneCorrectly() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).isoWeekYear()) @@ -1959,7 +1960,7 @@ public void shouldRenderIsoWeekYearWithTimezoneCorrectly() { } @Test // DATAMONGO-1548 - public void shouldRenderSwitchCorrectly() { + void shouldRenderSwitchCorrectly() { String expected = "$switch:\n" + // "{\n" + // @@ -2001,7 +2002,7 @@ public void shouldRenderSwitchCorrectly() { } @Test // DATAMONGO-1548 - public void shouldTypeCorrectly() { + void shouldTypeCorrectly() { Document agg = project().and(DataTypeOperators.Type.typeOf("a")).as("a").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2009,7 +2010,7 @@ public void shouldTypeCorrectly() { } @Test // DATAMONGO-1834 - public void shouldRenderDateFromPartsWithJustTheYear() { + void shouldRenderDateFromPartsWithJustTheYear() { Document agg = project().and(DateOperators.dateFromParts().year(2018)).as("newDate") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2018,7 +2019,7 @@ public void shouldRenderDateFromPartsWithJustTheYear() { } @Test // DATAMONGO-1834, DATAMONGO-2671 - public void shouldRenderDateFromParts() { + void shouldRenderDateFromParts() { Document agg = project() .and(DateOperators.dateFromParts().year(2018).month(3).day(23).hour(14).minute(25).second(10).millisecond(2)) @@ -2029,7 +2030,7 @@ public void shouldRenderDateFromParts() { } @Test // DATAMONGO-1834 - public void shouldRenderDateFromPartsWithTimezone() { + void shouldRenderDateFromPartsWithTimezone() { Document agg = project() .and(DateOperators.dateFromParts().withTimezone(Timezone.valueOf("America/Chicago")).year(2018)).as("newDate") @@ -2040,7 +2041,7 @@ public void shouldRenderDateFromPartsWithTimezone() { } @Test // DATAMONGO-1834 - public void shouldRenderIsoDateFromPartsWithJustTheYear() { + void shouldRenderIsoDateFromPartsWithJustTheYear() { Document agg = project().and(DateOperators.dateFromParts().isoWeekYear(2018)).as("newDate") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2049,7 +2050,7 @@ public void shouldRenderIsoDateFromPartsWithJustTheYear() { } @Test // DATAMONGO-1834, DATAMONGO-2671 - public void shouldRenderIsoDateFromParts() { + void shouldRenderIsoDateFromParts() { Document agg = project().and(DateOperators.dateFromParts().isoWeekYear(2018).isoWeek(12).isoDayOfWeek(5).hour(14) .minute(30).second(42).millisecond(2)).as("newDate").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2059,7 +2060,7 @@ public void shouldRenderIsoDateFromParts() { } @Test // DATAMONGO-1834 - public void shouldRenderIsoDateFromPartsWithTimezone() { + void shouldRenderIsoDateFromPartsWithTimezone() { Document agg = project() .and(DateOperators.dateFromParts().withTimezone(Timezone.valueOf("America/Chicago")).isoWeekYear(2018)) @@ -2070,7 +2071,7 @@ public void shouldRenderIsoDateFromPartsWithTimezone() { } @Test // DATAMONGO-1834 - public void shouldRenderDateToParts() { + void shouldRenderDateToParts() { Document agg = project().and(DateOperators.dateOf("date").toParts()).as("newDate") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2079,7 +2080,7 @@ public void shouldRenderDateToParts() { } @Test // DATAMONGO-1834 - public void shouldRenderDateToIsoParts() { + void shouldRenderDateToIsoParts() { Document agg = project().and(DateOperators.dateOf("date").toParts().iso8601()).as("newDate") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2089,7 +2090,7 @@ public void shouldRenderDateToIsoParts() { } @Test // DATAMONGO-1834 - public void shouldRenderDateToPartsWithTimezone() { + void shouldRenderDateToPartsWithTimezone() { Document agg = project() .and(DateOperators.dateOf("date").withTimezone(Timezone.valueOf("America/Chicago")).toParts()).as("newDate") @@ -2100,7 +2101,7 @@ public void shouldRenderDateToPartsWithTimezone() { } @Test // DATAMONGO-1834 - public void shouldRenderDateFromString() { + void shouldRenderDateFromString() { Document agg = project().and(DateOperators.dateFromString("2017-02-08T12:10:40.787")).as("newDate") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2110,7 +2111,7 @@ public void shouldRenderDateFromString() { } @Test // DATAMONGO-1834 - public void shouldRenderDateFromStringWithFieldReference() { + void shouldRenderDateFromStringWithFieldReference() { Document agg = project().and(DateOperators.dateOf("date").fromString()).as("newDate") .toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2120,7 +2121,7 @@ public void shouldRenderDateFromStringWithFieldReference() { } @Test // DATAMONGO-1834 - public void shouldRenderDateFromStringWithTimezone() { + void shouldRenderDateFromStringWithTimezone() { Document agg = project() .and(DateOperators.dateFromString("2017-02-08T12:10:40.787").withTimezone(Timezone.valueOf("America/Chicago"))) @@ -2131,7 +2132,7 @@ public void shouldRenderDateFromStringWithTimezone() { } @Test // DATAMONGO-2047 - public void shouldRenderDateFromStringWithFormat() { + void shouldRenderDateFromStringWithFormat() { Document agg = project().and(DateOperators.dateFromString("2017-02-08T12:10:40.787").withFormat("dd/mm/yyyy")) .as("newDate").toDocument(Aggregation.DEFAULT_CONTEXT); @@ -2141,7 +2142,7 @@ public void shouldRenderDateFromStringWithFormat() { } @Test // DATAMONGO-2200 - public void typeProjectionShouldIncludeTopLevelFieldsOfType() { + void typeProjectionShouldIncludeTopLevelFieldsOfType() { ProjectionOperation operation = Aggregation.project(Book.class); @@ -2155,7 +2156,7 @@ public void typeProjectionShouldIncludeTopLevelFieldsOfType() { } @Test // DATAMONGO-2200 - public void typeProjectionShouldMapFieldNames() { + void typeProjectionShouldMapFieldNames() { MongoMappingContext mappingContext = new MongoMappingContext(); MongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); @@ -2171,7 +2172,7 @@ public void typeProjectionShouldMapFieldNames() { } @Test // DATAMONGO-2200 - public void typeProjectionShouldIncludeInterfaceProjectionValues() { + void typeProjectionShouldIncludeInterfaceProjectionValues() { ProjectionOperation operation = Aggregation.project(ProjectionInterface.class); @@ -2184,7 +2185,7 @@ public void typeProjectionShouldIncludeInterfaceProjectionValues() { } @Test // DATAMONGO-2200 - public void typeProjectionShouldBeEmptyIfNoPropertiesFound() { + void typeProjectionShouldBeEmptyIfNoPropertiesFound() { ProjectionOperation operation = Aggregation.project(EmptyType.class); @@ -2195,7 +2196,7 @@ public void typeProjectionShouldBeEmptyIfNoPropertiesFound() { } @Test // DATAMONGO-2312 - public void simpleFieldReferenceAsArray() { + void simpleFieldReferenceAsArray() { org.bson.Document doc = Aggregation.newAggregation(project("x", "y", "someField").asArray("myArray")) .toDocument("coll", Aggregation.DEFAULT_CONTEXT); @@ -2205,7 +2206,7 @@ public void simpleFieldReferenceAsArray() { } @Test // DATAMONGO-2312 - public void mappedFieldReferenceAsArray() { + void mappedFieldReferenceAsArray() { MongoMappingContext mappingContext = new MongoMappingContext(); @@ -2219,7 +2220,7 @@ public void mappedFieldReferenceAsArray() { } @Test // DATAMONGO-2312 - public void arrayWithNullValue() { + void arrayWithNullValue() { Document doc = project() // .andArrayOf(Fields.field("field-1"), null, "value").as("myArray") // @@ -2229,7 +2230,7 @@ public void arrayWithNullValue() { } @Test // DATAMONGO-2312 - public void nestedArrayField() { + void nestedArrayField() { Document doc = project("_id", "value") // .andArrayOf(Fields.field("field-1"), "plain - string", ArithmeticOperators.valueOf("field-1").sum().and(10)) @@ -2241,7 +2242,7 @@ public void nestedArrayField() { } @Test // DATAMONGO-2312 - public void nestedMappedFieldReferenceInArrayField() { + void nestedMappedFieldReferenceInArrayField() { MongoMappingContext mappingContext = new MongoMappingContext(); @@ -2289,7 +2290,7 @@ interface ProjectionInterface { String getTitle(); } - static class EmptyType { + private static class EmptyType { } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 41b0323636..e92ea38336 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -32,6 +32,7 @@ * @author Thomas Darimont * @author Oliver Gierke * @author Christoph Strobl + * @author Divya Srivastava */ public class SpelExpressionTransformerUnitTests { @@ -800,68 +801,68 @@ void shouldRenderRtrimWithCharsFromFieldReference() { assertThat(transform("rtrim(field1, field2)")) .isEqualTo("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexFindWithoutOptions() { - + + @Test // GH-3725 + void shouldRenderRegexFindWithoutOptions() { + assertThat(transform("regexFind(field1,'e')")) - .isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}")); + .isEqualTo("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexFindWithOptions() { - + + @Test // GH-3725 + void shouldRenderRegexFindWithOptions() { + assertThat(transform("regexFind(field1,'e','i')")) - .isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}")); + .isEqualTo("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexFindWithOptionsFromFieldReference() { - + + @Test // GH-3725 + void shouldRenderRegexFindWithOptionsFromFieldReference() { + assertThat(transform("regexFind(field1,'e',field2)")) - .isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}")); + .isEqualTo("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexFindAllWithoutOptions() { - + + @Test // GH-3725 + void shouldRenderRegexFindAllWithoutOptions() { + assertThat(transform("regexFindAll(field1,'e')")) - .isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}")); + .isEqualTo("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexFindAllWithOptions() { - + + @Test // GH-3725 + void shouldRenderRegexFindAllWithOptions() { + assertThat(transform("regexFindAll(field1,'e','i')")) - .isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}")); + .isEqualTo("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexFindAllWithOptionsFromFieldReference() { - + + @Test // GH-3725 + void shouldRenderRegexFindAllWithOptionsFromFieldReference() { + assertThat(transform("regexFindAll(field1,'e',field2)")) - .isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}")); + .isEqualTo("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}"); } - @Test // DATAMONGO-3725 - public void shouldRenderRegexMatchWithoutOptions() { - + @Test // GH-3725 + void shouldRenderRegexMatchWithoutOptions() { + assertThat(transform("regexMatch(field1,'e')")) - .isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}")); + .isEqualTo("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexMatchWithOptions() { - + + @Test // GH-3725 + void shouldRenderRegexMatchWithOptions() { + assertThat(transform("regexMatch(field1,'e','i')")) - .isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}")); + .isEqualTo("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}"); } - - @Test // DATAMONGO-3725 - public void shouldRenderRegexMatchWithOptionsFromFieldReference() { - + + @Test // GH-3725 + void shouldRenderRegexMatchWithOptionsFromFieldReference() { + assertThat(transform("regexMatch(field1,'e',field2)")) - .isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}")); + .isEqualTo("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}"); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java index cdd0b38dbc..d8ba5129e0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/StringOperatorsUnitTests.java @@ -15,7 +15,9 @@ */ package org.springframework.data.mongodb.core.aggregation; -import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.test.util.Assertions.*; + +import java.util.regex.Pattern; import org.bson.Document; import org.junit.jupiter.api.Test; @@ -25,230 +27,258 @@ * * @author Christoph Strobl * @author Mark Paluch + * @author Divya Srivastava * @currentRead Royal Assassin - Robin Hobb */ -public class StringOperatorsUnitTests { +class StringOperatorsUnitTests { - static final String EXPRESSION_STRING = "{ \"$fitz\" : \"chivalry\" }"; - static final Document EXPRESSION_DOC = Document.parse(EXPRESSION_STRING); - static final AggregationExpression EXPRESSION = context -> EXPRESSION_DOC; + private static final String EXPRESSION_STRING = "{ \"$fitz\" : \"chivalry\" }"; + private static final Document EXPRESSION_DOC = Document.parse(EXPRESSION_STRING); + private static final AggregationExpression EXPRESSION = context -> EXPRESSION_DOC; @Test // DATAMONGO-2049 - public void shouldRenderTrim() { + void shouldRenderTrim() { assertThat(StringOperators.valueOf("shrewd").trim().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $trim: { \"input\" : \"$shrewd\" } } ")); + .isEqualTo("{ $trim: { \"input\" : \"$shrewd\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimForExpression() { + void shouldRenderTrimForExpression() { assertThat(StringOperators.valueOf(EXPRESSION).trim().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $trim: { \"input\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $trim: { \"input\" : " + EXPRESSION_STRING + " } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimWithChars() { + void shouldRenderTrimWithChars() { assertThat(StringOperators.valueOf("shrewd").trim("sh").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ")); + .isEqualTo("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimWithCharsExpression() { + void shouldRenderTrimWithCharsExpression() { assertThat(StringOperators.valueOf("shrewd").trim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimLeft() { + void shouldRenderTrimLeft() { assertThat(StringOperators.valueOf("shrewd").trim().left().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\" } } ")); + .isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimLeftWithChars() { + void shouldRenderTrimLeftWithChars() { assertThat(StringOperators.valueOf("shrewd").trim("sh").left().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ")); + .isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimRight() { + void shouldRenderTrimRight() { assertThat(StringOperators.valueOf("shrewd").trim().right().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\" } } ")); + .isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderTrimRightWithChars() { + void shouldRenderTrimRightWithChars() { assertThat(StringOperators.valueOf("shrewd").trim("sh").right().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ")); + .isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderLTrim() { + void shouldRenderLTrim() { assertThat(StringOperators.valueOf("shrewd").ltrim().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\" } } ")); + .isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderLTrimForExpression() { + void shouldRenderLTrimForExpression() { assertThat(StringOperators.valueOf(EXPRESSION).ltrim().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $ltrim: { \"input\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $ltrim: { \"input\" : " + EXPRESSION_STRING + " } } "); } @Test // DATAMONGO-2049 - public void shouldRenderLTrimWithChars() { + void shouldRenderLTrimWithChars() { assertThat(StringOperators.valueOf("shrewd").ltrim("sh").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ")); + .isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderLTrimWithCharsExpression() { + void shouldRenderLTrimWithCharsExpression() { assertThat(StringOperators.valueOf("shrewd").ltrim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } "); } @Test // DATAMONGO-2049 - public void shouldRenderRTrim() { + void shouldRenderRTrim() { assertThat(StringOperators.valueOf("shrewd").rtrim().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\" } } ")); + .isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderRTrimForExpression() { + void shouldRenderRTrimForExpression() { assertThat(StringOperators.valueOf(EXPRESSION).rtrim().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $rtrim: { \"input\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $rtrim: { \"input\" : " + EXPRESSION_STRING + " } } "); } @Test // DATAMONGO-2049 - public void shouldRenderRTrimWithChars() { + void shouldRenderRTrimWithChars() { assertThat(StringOperators.valueOf("shrewd").rtrim("sh").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ")); + .isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "); } @Test // DATAMONGO-2049 - public void shouldRenderRTrimWithCharsExpression() { + void shouldRenderRTrimWithCharsExpression() { assertThat(StringOperators.valueOf("shrewd").rtrim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindAll() { + + @Test // GH-3725 + void shouldRenderRegexFindAll() { assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }")); + .isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }"); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindAllForExpression() { + + @Test // GH-3725 + void shouldRenderRegexFindAllForExpression() { assertThat(StringOperators.valueOf(EXPRESSION).regexFindAll("e").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ")); + .isEqualTo("{ $regexFindAll: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindAllForRegexExpression() { + + @Test // GH-3725 + void shouldRenderRegexFindAllForRegexExpression() { assertThat(StringOperators.valueOf("shrewd").regexFindAll(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } "); + } + + @Test // GH-3725 + void shouldRenderRegexFindAllWithPattern() { + + assertThat(StringOperators.valueOf("shrewd") + .regexFindAll( + Pattern.compile("foo", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL | Pattern.COMMENTS)) + .toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"foo\" , \"options\" : \"imsx\" } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindAllWithOptions() { + + @Test // GH-3725 + void shouldRenderRegexFindAllWithOptions() { assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ")); + .isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindAllWithOptionsExpression() { + + @Test // GH-3725 + void shouldRenderRegexFindAllWithOptionsExpression() { assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + + " } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexMatch() { + + @Test // GH-3725 + void shouldRenderRegexMatch() { assertThat(StringOperators.valueOf("shrewd").regexMatch("e").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }")); + .isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }"); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexMatchForExpression() { + + @Test // GH-3725 + void shouldRenderRegexMatchForExpression() { assertThat(StringOperators.valueOf(EXPRESSION).regexMatch("e").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ")); + .isEqualTo("{ $regexMatch: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexMatchForRegexExpression() { + + @Test // GH-3725 + void shouldRenderRegexMatchForRegexExpression() { assertThat(StringOperators.valueOf("shrewd").regexMatch(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } "); + } + + @Test // GH-3725 + void shouldRenderRegexMatchForPattern() { + + assertThat(StringOperators.valueOf("shrewd").regexMatch(Pattern.compile("foo", Pattern.CASE_INSENSITIVE)) + .toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"foo\", \"options\" : \"i\"} } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexMatchWithOptions() { + + @Test // GH-3725 + void shouldRenderRegexMatchWithOptions() { assertThat(StringOperators.valueOf("shrewd").regexMatch("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ")); + .isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexMatchWithOptionsExpression() { + + @Test // GH-3725 + void shouldRenderRegexMatchWithOptionsExpression() { assertThat(StringOperators.valueOf("shrewd").regexMatch("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + + " } } "); } - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFind() { + @Test // GH-3725 + void shouldRenderRegexFind() { assertThat(StringOperators.valueOf("shrewd").regexFind("e").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }")); + .isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }"); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindForExpression() { + + @Test // GH-3725 + void shouldRenderRegexFindForExpression() { assertThat(StringOperators.valueOf(EXPRESSION).regexFind("e").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFind: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ")); + .isEqualTo("{ $regexFind: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindForRegexExpression() { + + @Test // GH-3725 + void shouldRenderRegexFindForRegexExpression() { assertThat(StringOperators.valueOf("shrewd").regexFind(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ")); + .isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindWithOptions() { - assertThat(StringOperators.valueOf("shrewd").regexFind("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ")); + @Test // GH-3725 + void shouldRenderRegexFindForPattern() { + + assertThat(StringOperators.valueOf("shrewd").regexFind(Pattern.compile("foo", Pattern.MULTILINE)) + .toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"foo\", \"options\" : \"m\"} } "); } - - @Test // DATAMONGO - 3725 - public void shouldRenderRegexFindWithOptionsExpression() { - assertThat(StringOperators.valueOf("shrewd").regexFind("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } ")); + @Test // GH-3725 + void shouldRenderRegexFindWithOptions() { + + assertThat(StringOperators.valueOf("shrewd").regexFind("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } "); } + @Test // GH-3725 + void shouldRenderRegexFindWithOptionsExpression() { + assertThat(StringOperators.valueOf("shrewd").regexFind("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + + " } } "); + } } diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index f96719adde..75ed415096 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -88,7 +88,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `abs`, `add` (+++*+++ via `plus`), `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` | String Aggregation Operators -| `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` +| `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `regexFind`, `regexFindAll`, `regexMatch`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` | Comparison Aggregation Operators | `eq` (+++*+++ via `is`), `gt`, `gte`, `lt`, `lte`, `ne` From 62eb719b1e9adb050c33be254cbe9bf7a527415e Mon Sep 17 00:00:00 2001 From: James McNee Date: Thu, 26 Aug 2021 21:25:36 +0100 Subject: [PATCH 0520/1381] Add support for `$sampleRate` criteria. Closes #3726 Original pull request: #3765. --- .../data/mongodb/core/query/Criteria.java | 16 ++++++++++++++++ .../mongodb/core/query/CriteriaUnitTests.java | 16 ++++++++++++++++ .../asciidoc/reference/mongo-repositories.adoc | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index f9a354c38f..3ec4caf3c7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -64,6 +64,7 @@ * @author Andreas Zink * @author Ziemowit Stolarczyk * @author Clément Petit + * @author James McNee */ public class Criteria implements CriteriaDefinition { @@ -390,6 +391,21 @@ public Criteria exists(boolean value) { return this; } + /** + * Creates a criterion using the {@literal $sampleRate} operator. + * + * @param sampleRate sample rate to determine number of documents to be randomly selected from the input. + * @return this. + * @see MongoDB Query operator: $sampleRate + */ + public Criteria sampleRate(double sampleRate) { + Assert.isTrue(sampleRate >= 0, "The sample rate must be greater than zero!"); + Assert.isTrue(sampleRate <= 1, "The sample rate must not be greater than one!"); + + criteria.put("$sampleRate", sampleRate); + return this; + } + /** * Creates a criterion using the {@literal $type} operator. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java index 9edf3c43fd..e24fc34bef 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java @@ -156,6 +156,22 @@ public void shouldNegateFollowingSimpleExpression() { assertThat(co).isEqualTo(Document.parse("{ \"age\" : { \"$not\" : { \"$gt\" : 18}} , \"status\" : \"student\"}")); } + @Test // GH-3726 + public void shouldBuildCorrectSampleRateOperation() { + Criteria c = new Criteria().sampleRate(0.4); + assertThat(c.getCriteriaObject()).isEqualTo(Document.parse("{ \"$sampleRate\" : 0.4 }")); + } + + @Test // GH-3726 + public void shouldThrowExceptionWhenSampleRateIsNegative() { + assertThatIllegalArgumentException().isThrownBy(() -> new Criteria().sampleRate(-1)); + } + + @Test // GH-3726 + public void shouldThrowExceptionWhenSampleRateIsGreatedThanOne() { + assertThatIllegalArgumentException().isThrownBy(() -> new Criteria().sampleRate(1.01)); + } + @Test // DATAMONGO-1068 public void getCriteriaObjectShouldReturnEmptyDocumentWhenNoCriteriaSpecified() { diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index 328a547b5a..b847174c67 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -281,6 +281,10 @@ lower / upper bounds (`$gt` / `$gte` & `$lt` / `$lte`) according to `Range` | `Exists` | `findByLocationExists(boolean exists)` | `{"location" : {"$exists" : exists }}` + +| `SampleRate` +| `sampleRate(double sampleRate)` +| `{"$sampleRate" : sampleRate }` |=== NOTE: If the property criterion compares a document, the order of the fields and exact equality in the document matters. From f662d7ca0d240a9f719ffec78243fc7661c544a1 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 27 Aug 2021 09:34:40 +0200 Subject: [PATCH 0521/1381] Polishing. Tweak Javadoc. Add since tag, reformat code. Simplify tests. Move documentation bits into the right place. See #3726. Original pull request: #3765. --- .../data/mongodb/core/query/Criteria.java | 8 ++++-- .../mongodb/core/query/CriteriaUnitTests.java | 27 ++++++++++--------- .../reference/mongo-repositories.adoc | 4 --- src/main/asciidoc/reference/mongodb.adoc | 1 + 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 3ec4caf3c7..df167330a1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -394,11 +394,15 @@ public Criteria exists(boolean value) { /** * Creates a criterion using the {@literal $sampleRate} operator. * - * @param sampleRate sample rate to determine number of documents to be randomly selected from the input. + * @param sampleRate sample rate to determine number of documents to be randomly selected from the input. Must be + * between {@code 0} and {@code 1}. * @return this. - * @see MongoDB Query operator: $sampleRate + * @see MongoDB Query operator: + * $sampleRate + * @since 3.3 */ public Criteria sampleRate(double sampleRate) { + Assert.isTrue(sampleRate >= 0, "The sample rate must be greater than zero!"); Assert.isTrue(sampleRate <= 1, "The sample rate must not be greater than one!"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java index e24fc34bef..96253e4ac0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java @@ -40,19 +40,20 @@ * @author Ziemowit Stolarczyk * @author Clément Petit * @author Mark Paluch + * @author James McNee */ public class CriteriaUnitTests { @Test public void testSimpleCriteria() { Criteria c = new Criteria("name").is("Bubba"); - assertThat(c.getCriteriaObject()).isEqualTo(Document.parse("{ \"name\" : \"Bubba\"}")); + assertThat(c.getCriteriaObject()).isEqualTo("{ \"name\" : \"Bubba\"}"); } @Test public void testNotEqualCriteria() { Criteria c = new Criteria("name").ne("Bubba"); - assertThat(c.getCriteriaObject()).isEqualTo(Document.parse("{ \"name\" : { \"$ne\" : \"Bubba\"}}")); + assertThat(c.getCriteriaObject()).isEqualTo("{ \"name\" : { \"$ne\" : \"Bubba\"}}"); } @Test @@ -67,7 +68,7 @@ public void buildsIsNullCriteriaCorrectly() { @Test public void testChainedCriteria() { Criteria c = new Criteria("name").is("Bubba").and("age").lt(21); - assertThat(c.getCriteriaObject()).isEqualTo(Document.parse("{ \"name\" : \"Bubba\" , \"age\" : { \"$lt\" : 21}}")); + assertThat(c.getCriteriaObject()).isEqualTo("{ \"name\" : \"Bubba\" , \"age\" : { \"$lt\" : 21}}"); } @Test(expected = InvalidMongoDbApiUsageException.class) @@ -153,13 +154,13 @@ public void shouldNegateFollowingSimpleExpression() { Document co = c.getCriteriaObject(); assertThat(co).isNotNull(); - assertThat(co).isEqualTo(Document.parse("{ \"age\" : { \"$not\" : { \"$gt\" : 18}} , \"status\" : \"student\"}")); + assertThat(co).isEqualTo("{ \"age\" : { \"$not\" : { \"$gt\" : 18}} , \"status\" : \"student\"}"); } @Test // GH-3726 public void shouldBuildCorrectSampleRateOperation() { Criteria c = new Criteria().sampleRate(0.4); - assertThat(c.getCriteriaObject()).isEqualTo(Document.parse("{ \"$sampleRate\" : 0.4 }")); + assertThat(c.getCriteriaObject()).isEqualTo("{ \"$sampleRate\" : 0.4 }"); } @Test // GH-3726 @@ -302,7 +303,7 @@ public void shouldAppendBitsAllClearWithIntBitmaskCorrectly() { Criteria numericBitmaskCriteria = new Criteria("field").bits().allClear(0b101); assertThat(numericBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAllClear\" : 5} }")); + .isEqualTo("{ \"field\" : { \"$bitsAllClear\" : 5} }"); } @Test // DATAMONGO-1808 @@ -311,7 +312,7 @@ public void shouldAppendBitsAllClearWithPositionListCorrectly() { Criteria bitPositionsBitmaskCriteria = new Criteria("field").bits().allClear(Arrays.asList(0, 2)); assertThat(bitPositionsBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAllClear\" : [ 0, 2 ]} }")); + .isEqualTo("{ \"field\" : { \"$bitsAllClear\" : [ 0, 2 ]} }"); } @Test // DATAMONGO-1808 @@ -320,7 +321,7 @@ public void shouldAppendBitsAllSetWithIntBitmaskCorrectly() { Criteria numericBitmaskCriteria = new Criteria("field").bits().allSet(0b101); assertThat(numericBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAllSet\" : 5} }")); + .isEqualTo("{ \"field\" : { \"$bitsAllSet\" : 5} }"); } @Test // DATAMONGO-1808 @@ -329,7 +330,7 @@ public void shouldAppendBitsAllSetWithPositionListCorrectly() { Criteria bitPositionsBitmaskCriteria = new Criteria("field").bits().allSet(Arrays.asList(0, 2)); assertThat(bitPositionsBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAllSet\" : [ 0, 2 ]} }")); + .isEqualTo("{ \"field\" : { \"$bitsAllSet\" : [ 0, 2 ]} }"); } @Test // DATAMONGO-1808 @@ -338,7 +339,7 @@ public void shouldAppendBitsAnyClearWithIntBitmaskCorrectly() { Criteria numericBitmaskCriteria = new Criteria("field").bits().anyClear(0b101); assertThat(numericBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAnyClear\" : 5} }")); + .isEqualTo("{ \"field\" : { \"$bitsAnyClear\" : 5} }"); } @Test // DATAMONGO-1808 @@ -347,7 +348,7 @@ public void shouldAppendBitsAnyClearWithPositionListCorrectly() { Criteria bitPositionsBitmaskCriteria = new Criteria("field").bits().anyClear(Arrays.asList(0, 2)); assertThat(bitPositionsBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAnyClear\" : [ 0, 2 ]} }")); + .isEqualTo("{ \"field\" : { \"$bitsAnyClear\" : [ 0, 2 ]} }"); } @Test // DATAMONGO-1808 @@ -356,7 +357,7 @@ public void shouldAppendBitsAnySetWithIntBitmaskCorrectly() { Criteria numericBitmaskCriteria = new Criteria("field").bits().anySet(0b101); assertThat(numericBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAnySet\" : 5} }")); + .isEqualTo("{ \"field\" : { \"$bitsAnySet\" : 5} }"); } @Test // DATAMONGO-1808 @@ -365,7 +366,7 @@ public void shouldAppendBitsAnySetWithPositionListCorrectly() { Criteria bitPositionsBitmaskCriteria = new Criteria("field").bits().anySet(Arrays.asList(0, 2)); assertThat(bitPositionsBitmaskCriteria.getCriteriaObject()) - .isEqualTo(Document.parse("{ \"field\" : { \"$bitsAnySet\" : [ 0, 2 ]} }")); + .isEqualTo("{ \"field\" : { \"$bitsAnySet\" : [ 0, 2 ]} }"); } @Test // DATAMONGO-2002 diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index b847174c67..328a547b5a 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -281,10 +281,6 @@ lower / upper bounds (`$gt` / `$gte` & `$lt` / `$lte`) according to `Range` | `Exists` | `findByLocationExists(boolean exists)` | `{"location" : {"$exists" : exists }}` - -| `SampleRate` -| `sampleRate(double sampleRate)` -| `{"$sampleRate" : sampleRate }` |=== NOTE: If the property criterion compares a document, the order of the fields and exact equality in the document matters. diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index f214edba4c..7bf034f461 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -1219,6 +1219,7 @@ The `Criteria` class provides the following methods, all of which correspond to * `Criteria` *orOperator* `(Criteria... criteria)` Creates an or query using the `$or` operator for all of the provided criteria * `Criteria` *orOperator* `(Collection criteria)` Creates an or query using the `$or` operator for all of the provided criteria * `Criteria` *regex* `(String re)` Creates a criterion using a `$regex` +* `Criteria` *sampleRate* `(double sampleRate)` Creates a criterion using the `$sampleRate` operator * `Criteria` *size* `(int s)` Creates a criterion using the `$size` operator * `Criteria` *type* `(int t)` Creates a criterion using the `$type` operator * `Criteria` *matchingDocumentStructure* `(MongoJsonSchema schema)` Creates a criterion using the `$jsonSchema` operator for <>. `$jsonSchema` can only be applied on the top level of a query and not property specific. Use the `properties` attribute of the schema to match against nested fields. From bf86f39b2d5bc2d3c197fbff90551b85b440474a Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 24 Aug 2021 07:31:25 +0200 Subject: [PATCH 0522/1381] Fix id field target type conversion for document references. This commit fixes an issue where a defined custom target type conversion for the id field was not properly considered when writing a document reference. Previously an eg. String was not being converted into an ObjectId correctly causing lookup queries to return empty results. Converting the id property value on write solves the issue. Includes a minor polish in the mapping centralizing pointer creation within the DocumentPointerFactory. Closes: #3782 Original pull request: #3785. --- .../core/convert/DocumentPointerFactory.java | 11 ++- .../core/convert/MappingMongoConverter.java | 23 ++--- .../MongoTemplateDocumentReferenceTests.java | 98 ++++++++++++++++++- 3 files changed, 114 insertions(+), 18 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java index 09d69e4b27..b30aa957de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java @@ -83,7 +83,16 @@ DocumentPointer computePointer( .getRequiredPersistentEntity(property.getAssociationTargetType()); if (usesDefaultLookup(property)) { - return () -> persistentEntity.getIdentifierAccessor(value).getIdentifier(); + + MongoPersistentProperty idProperty = persistentEntity.getIdProperty(); + Object idValue = persistentEntity.getIdentifierAccessor(value).getIdentifier(); + + if (idProperty.hasExplicitWriteTarget() + && conversionService.canConvert(idValue.getClass(), idProperty.getFieldType())) { + return () -> conversionService.convert(idValue, idProperty.getFieldType()); + } + + return () -> idValue; } MongoPersistentEntity valueEntity = mappingContext.getPersistentEntity(value.getClass()); 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 48505559c0..a60c853c33 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 @@ -869,15 +869,12 @@ protected List createCollection(Collection collection, MongoPersisten if (!property.isDbReference()) { if (property.isAssociation()) { - return writeCollectionInternal(collection.stream().map(it -> { - if (conversionService.canConvert(it.getClass(), DocumentPointer.class)) { - return conversionService.convert(it, DocumentPointer.class).getPointer(); - } else { - // just take the id as a reference - return mappingContext.getPersistentEntity(property.getAssociationTargetType()).getIdentifierAccessor(it) - .getIdentifier(); - } - }).collect(Collectors.toList()), ClassTypeInformation.from(DocumentPointer.class), new ArrayList<>()); + + List targetCollection = collection.stream().map(it -> { + return documentPointerFactory.computePointer(mappingContext, property, it, property.getActualType()).getPointer(); + }).collect(Collectors.toList()); + + return writeCollectionInternal(targetCollection, ClassTypeInformation.from(DocumentPointer.class), new ArrayList<>()); } if (property.hasExplicitWriteTarget()) { @@ -930,13 +927,7 @@ protected Bson createMap(Map map, MongoPersistentProperty proper if (property.isDbReference()) { document.put(simpleKey, value != null ? createDBRef(value, property) : null); } else { - if (conversionService.canConvert(value.getClass(), DocumentPointer.class)) { - document.put(simpleKey, conversionService.convert(value, DocumentPointer.class).getPointer()); - } else { - // just take the id as a reference - document.put(simpleKey, mappingContext.getPersistentEntity(property.getAssociationTargetType()) - .getIdentifierAccessor(value).getIdentifier()); - } + document.put(simpleKey, documentPointerFactory.computePointer(mappingContext, property, value, property.getActualType()).getPointer()); } } else { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index fa1deb4f1c..d6bcc10e49 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -32,6 +32,7 @@ import java.util.Map; import org.bson.Document; +import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -44,6 +45,8 @@ import org.springframework.data.mongodb.core.mapping.DocumentPointer; import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.FieldType; +import org.springframework.data.mongodb.core.mapping.MongoId; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.MongoClientExtension; @@ -106,6 +109,26 @@ void writeSimpleTypeReference() { assertThat(target.get("simpleValueRef")).isEqualTo("ref-1"); } + @Test // GH-3782 + void writeTypeReferenceHavingCustomizedIdTargetType() { + + ObjectId expectedIdValue = new ObjectId(); + String rootCollectionName = template.getCollectionName(SingleRefRoot.class); + + SingleRefRoot source = new SingleRefRoot(); + source.id = "root-1"; + source.customIdTargetRef = new ObjectRefHavingCustomizedIdTargetType(expectedIdValue.toString(), + "me-the-referenced-object"); + + template.save(source); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target.get("customIdTargetRef")).isEqualTo(expectedIdValue); + } + @Test // GH-3602 void writeMapTypeReference() { @@ -126,6 +149,26 @@ void writeMapTypeReference() { assertThat(target.get("mapValueRef", Map.class)).containsEntry("frodo", "ref-1").containsEntry("bilbo", "ref-2"); } + @Test // GH-3782 + void writeMapOfTypeReferenceHavingCustomizedIdTargetType() { + + ObjectId expectedIdValue = new ObjectId(); + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + CollectionRefRoot source = new CollectionRefRoot(); + source.id = "root-1"; + source.customIdTargetRefMap = Collections.singletonMap("frodo", + new ObjectRefHavingCustomizedIdTargetType(expectedIdValue.toString(), "me-the-referenced-object")); + + template.save(source); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target.get("customIdTargetRefMap", Map.class)).containsEntry("frodo", expectedIdValue); + } + @Test // GH-3602 void writeCollectionOfSimpleTypeReference() { @@ -145,6 +188,26 @@ void writeCollectionOfSimpleTypeReference() { assertThat(target.get("simpleValueRef", List.class)).containsExactly("ref-1", "ref-2"); } + @Test // GH-3782 + void writeListOfTypeReferenceHavingCustomizedIdTargetType() { + + ObjectId expectedIdValue = new ObjectId(); + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + CollectionRefRoot source = new CollectionRefRoot(); + source.id = "root-1"; + source.customIdTargetRefList = Collections.singletonList( + new ObjectRefHavingCustomizedIdTargetType(expectedIdValue.toString(), "me-the-referenced-object")); + + template.save(source); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target.get("customIdTargetRefList", List.class)).containsExactly(expectedIdValue); + } + @Test // GH-3602 void writeObjectTypeReference() { @@ -739,6 +802,26 @@ void updateReferenceWithValue() { assertThat(target).containsEntry("toB", "b"); } + @Test // GH-3782 + void updateReferenceHavingCustomizedIdTargetType() { + + ObjectId expectedIdValue = new ObjectId(); + String rootCollectionName = template.getCollectionName(SingleRefRoot.class); + + SingleRefRoot root = new SingleRefRoot(); + root.id = "root-1"; + template.save(root); + + template.update(SingleRefRoot.class).apply(new Update().set("customIdTargetRef", + new ObjectRefHavingCustomizedIdTargetType(expectedIdValue.toString(), "b"))).first(); + + Document target = template.execute(db -> { + return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first(); + }); + + assertThat(target).containsEntry("customIdTargetRef", expectedIdValue); + } + @Test // GH-3602 void updateReferenceCollectionWithEntity() { @@ -998,6 +1081,8 @@ static class SingleRefRoot { @DocumentReference(lookup = "{ 'refKey1' : '?#{refKey1}', 'refKey2' : '?#{refKey2}' }", lazy = true) // ObjectRefOnNonIdField lazyObjectValueRefOnNonIdFields; + + @DocumentReference ObjectRefHavingCustomizedIdTargetType customIdTargetRef; } @Data @@ -1027,6 +1112,10 @@ static class CollectionRefRoot { @DocumentReference(lookup = "{ 'refKey1' : '?#{refKey1}', 'refKey2' : '?#{refKey2}' }") // List objectValueRefOnNonIdFields; + + @DocumentReference List customIdTargetRefList; + + @DocumentReference Map customIdTargetRefMap; } @FunctionalInterface @@ -1094,6 +1183,14 @@ public Object toReference() { } } + @Data + @AllArgsConstructor + static class ObjectRefHavingCustomizedIdTargetType { + + @MongoId(targetType = FieldType.OBJECT_ID) String id; + String name; + } + static class ReferencableConverter implements Converter> { @Nullable @@ -1196,5 +1293,4 @@ static class UsingAtReference { @Reference // Publisher publisher; } - } From f24e8e5361bf02484e20dc7799bc2a13b808873e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 1 Sep 2021 10:39:36 +0200 Subject: [PATCH 0523/1381] Avoid nested Document conversion to primitive types for fields with an explicit write target. We now no longer attempt to convert query Documents into primitive types to avoid e.g. Document to String conversion. Closes: #3783 Original Pull Request: #3797 --- .../mongodb/core/convert/QueryMapper.java | 3 +- .../core/convert/QueryMapperUnitTests.java | 31 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 7a14f07c4c..e7deb38231 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -778,7 +778,8 @@ protected boolean isKeyword(String candidate) { @Nullable private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) { - if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) { + if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget() + || value instanceof Document || value instanceof DBObject) { return value; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index efd354b866..808263697a 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -33,8 +33,7 @@ import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; @@ -83,9 +82,12 @@ public class QueryMapperUnitTests { @BeforeEach void beforeEach() { + MongoCustomConversions conversions = new MongoCustomConversions(); this.context = new MongoMappingContext(); + this.context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); + this.converter.setCustomConversions(conversions); this.converter.afterPropertiesSet(); this.mapper = new QueryMapper(converter); @@ -1335,6 +1337,25 @@ void mapStringIdFieldProjection() { assertThat(mappedFields).containsEntry("_id", 1); } + @Test // GH-3783 + void retainsId$InWithStringArray() { + + org.bson.Document mappedQuery = mapper.getMappedObject( + org.bson.Document.parse("{ _id : { $in: [\"5b8bedceb1e0bfc07b008828\"]}}"), + context.getPersistentEntity(WithExplicitStringId.class)); + assertThat(mappedQuery.get("_id")).isEqualTo(org.bson.Document.parse("{ $in: [\"5b8bedceb1e0bfc07b008828\"]}")); + } + + @Test // GH-3783 + void mapsId$InInToObjectIds() { + + org.bson.Document mappedQuery = mapper.getMappedObject( + org.bson.Document.parse("{ _id : { $in: [\"5b8bedceb1e0bfc07b008828\"]}}"), + context.getPersistentEntity(ClassWithDefaultId.class)); + assertThat(mappedQuery.get("_id")) + .isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}")); + } + class WithDeepArrayNesting { List level0; @@ -1404,6 +1425,12 @@ class WithStringId { String name; } + class WithExplicitStringId { + + @MongoId(FieldType.STRING) String id; + String name; + } + class BigIntegerId { @Id private BigInteger id; From e71ec874ab69ecc3cfd199be5ce9cda76686913e Mon Sep 17 00:00:00 2001 From: divyajnu08 Date: Sun, 29 Aug 2021 16:41:52 +0530 Subject: [PATCH 0524/1381] Add support for `$expr` operator. Also, allow construction of $match with an AggregationExpression. Closes #3790 --- .../core/aggregation/AddFieldsOperation.java | 1 + .../mongodb/core/aggregation/Aggregation.java | 12 +- .../core/aggregation/EvaluationOperators.java | 109 ++++++++++++++++++ .../core/aggregation/MatchOperation.java | 39 ++++++- .../aggregation/ReplaceRootOperation.java | 1 + .../core/aggregation/SetOperation.java | 1 + .../aggregation/MatchOperationUnitTests.java | 26 +++++ .../aggregation/SetOperationUnitTests.java | 1 + 8 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java index 3f3dd125d1..90cc828591 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AddFieldsOperation.java @@ -201,4 +201,5 @@ public interface ValueAppender { AddFieldsOperationBuilder withValueOfExpression(String operation, Object... values); } } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index cecc8f2554..55964bab93 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -498,7 +498,17 @@ public static MatchOperation match(Criteria criteria) { public static MatchOperation match(CriteriaDefinition criteria) { return new MatchOperation(criteria); } - + + /** + * Creates a new {@link MatchOperation} + * + * @return new instance of {@link MatchOperation}. + * @since 1.10 + */ + public static MatchOperation match() { + return new MatchOperation(); + } + /** * Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the {@code distanceField}. The * {@code distanceField} defines output field that contains the calculated distance. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java new file mode 100644 index 0000000000..0fb8e25fab --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java @@ -0,0 +1,109 @@ +package org.springframework.data.mongodb.core.aggregation; + +import org.springframework.util.Assert; + +public class EvaluationOperators { + + /** + * Take the value resulting from the given fieldReference. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link EvaluationOperatorFactory}. + */ + public static EvaluationOperatorFactory valueOf(String fieldReference) { + return new EvaluationOperatorFactory(fieldReference); + } + + /** + * Take the value resulting from the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link EvaluationOperatorFactory}. + */ + public static EvaluationOperatorFactory valueOf(AggregationExpression expression) { + return new EvaluationOperatorFactory(expression); + } + + public static class EvaluationOperatorFactory { + + private final String fieldReference; + private final AggregationExpression expression; + + /** + * Creates new {@link EvaluationOperatorFactory} for given {@literal fieldReference}. + * + * @param fieldReference must not be {@literal null}. + */ + public EvaluationOperatorFactory(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + this.fieldReference = fieldReference; + this.expression = null; + } + + + /** + * Creates new {@link EvaluationOperatorFactory} for given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + */ + public EvaluationOperatorFactory(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + this.fieldReference = null; + this.expression = expression; + } + + /** + * Creates new {@link AggregationExpression} that is a valid aggregation expression. + * + * @return new instance of {@link Expr}. + */ + public Expr expr() { + return usesFieldRef() ? Expr.valueOf(fieldReference) : Expr.valueOf(expression); + } + + + public static class Expr extends AbstractAggregationExpression { + + private Expr(Object value) { + super(value); + } + + @Override + protected String getMongoMethod() { + return "$expr"; + } + + /** + * Creates new {@link Expr}. + * + * @param fieldReference must not be {@literal null}. + * @return new instance of {@link Expr}. + */ + public static Expr valueOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new Expr(Fields.field(fieldReference)); + } + + /** + * Creates new {@link Expr}. + * + * @param expression must not be {@literal null}. + * @return new instance of {@link Expr}. + */ + public static Expr valueOf(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + return new Expr(expression); + } + + } + + private boolean usesFieldRef() { + return fieldReference != null; + } + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index c9d83ae6c8..c2796aaa03 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.core.aggregation; import org.bson.Document; +import org.springframework.data.mongodb.core.aggregation.EvaluationOperators.EvaluationOperatorFactory.Expr; import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.util.Assert; @@ -36,7 +37,16 @@ public class MatchOperation implements AggregationOperation { private final CriteriaDefinition criteriaDefinition; - + private final AggregationExpression expression; + + /** + * Creates a new {@link MatchOperation} + */ + public MatchOperation() { + this.criteriaDefinition = null; + this.expression = null; + } + /** * Creates a new {@link MatchOperation} for the given {@link CriteriaDefinition}. * @@ -46,14 +56,39 @@ public MatchOperation(CriteriaDefinition criteriaDefinition) { Assert.notNull(criteriaDefinition, "Criteria must not be null!"); this.criteriaDefinition = criteriaDefinition; + this.expression = null; } - + + /** + * Creates a new {@link MatchOperation} for the given {@link Expression}. + * + * @param criteriaDefinition must not be {@literal null}. + */ + private MatchOperation(Expr expression) { + Assert.notNull(expression, "Expression must not be null!"); + this.criteriaDefinition = null; + this.expression = expression; + } + + /** + * Creates a new {@link MatchOperation} for the given {@link AggregationExpression}. + * + * @param expression must not be {@literal null}. + */ + public MatchOperation withValueOf(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); + return new MatchOperation(EvaluationOperators.valueOf(expression).expr()); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) */ @Override public Document toDocument(AggregationOperationContext context) { + if(expression != null) { + return new Document(getOperator(), expression.toDocument()); + } return new Document(getOperator(), context.getMappedObject(criteriaDefinition.getCriteriaObject())); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java index c452ffb8ea..94f9785595 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperation.java @@ -21,6 +21,7 @@ import java.util.List; import org.bson.Document; + import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField; import org.springframework.expression.spel.ast.Projection; import org.springframework.util.Assert; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java index 731668ed3c..d065f81662 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SetOperation.java @@ -193,5 +193,6 @@ public interface ValueAppender { */ SetOperation withValueOfExpression(String operation, Object... values); } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java new file mode 100644 index 0000000000..04d3824de1 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java @@ -0,0 +1,26 @@ +package org.springframework.data.mongodb.core.aggregation; + +import static org.assertj.core.api.Assertions.*; + +import org.bson.Document; +import org.junit.jupiter.api.Test; + +class MatchOperationUnitTests { + + @Test // DATAMONGO - 3729 + public void shouldRenderStdDevPopCorrectly() { + MatchOperation operation = Aggregation.match().withValueOf(ArithmeticOperators.valueOf("quiz").stdDevPop()); + assertThat(operation.toDocument(Aggregation.DEFAULT_CONTEXT)). + isEqualTo(Document.parse("{ $match: { \"$expr\" : { \"$stdDevPop\" : \"$quiz\" } } } ")); + + } + + @Test // DATAMONGO - 3729 + public void shouldRenderStdDevSampCorrectly() { + MatchOperation operation = Aggregation.match().withValueOf(ArithmeticOperators.valueOf("quiz").stdDevSamp()); + assertThat(operation.toDocument(Aggregation.DEFAULT_CONTEXT)). + isEqualTo(Document.parse("{ $match: { \"$expr\" : { \"$stdDevSamp\" : \"$quiz\" } } } ")); + + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java index b90b049da1..8fd8bd5526 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java @@ -21,6 +21,7 @@ import org.bson.Document; import org.junit.jupiter.api.Test; + import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; import org.springframework.data.mongodb.core.convert.QueryMapper; From 34d66a276ac35a24f076d565543803e4392c5880 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 6 Sep 2021 15:07:02 +0200 Subject: [PATCH 0525/1381] Polishing. Add license headers. Update Javadoc, author, and since tags. Add tests. Add toCriteriaDefinition method. See #3790 --- .../mongodb/core/aggregation/Aggregation.java | 13 ++-- .../core/aggregation/EvaluationOperators.java | 66 ++++++++++++++++--- .../core/aggregation/MatchOperation.java | 44 +++++-------- .../EvaluationOperatorsUnitTests.java | 35 ++++++++++ .../aggregation/MatchOperationUnitTests.java | 29 ++++---- .../ReplaceRootOperationUnitTests.java | 16 ++--- .../ReplaceWithOperationUnitTests.java | 8 +-- .../core/convert/QueryMapperUnitTests.java | 18 +++++ 8 files changed, 156 insertions(+), 73 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperatorsUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 55964bab93..614489692c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -498,17 +498,18 @@ public static MatchOperation match(Criteria criteria) { public static MatchOperation match(CriteriaDefinition criteria) { return new MatchOperation(criteria); } - + /** - * Creates a new {@link MatchOperation} + * Creates a new {@link MatchOperation} using the given {@link AggregationExpression}. * + * @param expression must not be {@literal null}. * @return new instance of {@link MatchOperation}. - * @since 1.10 + * @since 3.3 */ - public static MatchOperation match() { - return new MatchOperation(); + public static MatchOperation match(AggregationExpression expression) { + return new MatchOperation(expression); } - + /** * Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the {@code distanceField}. The * {@code distanceField} defines output field that contains the calculated distance. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java index 0fb8e25fab..181bab5ef5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperators.java @@ -1,9 +1,33 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; +import org.bson.Document; + +import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.util.Assert; +/** + * Gateway to {@literal evaluation operators} such as {@literal $expr}. + * + * @author Divya Srivastava + * @since 3.3 + */ public class EvaluationOperators { - + /** * Take the value resulting from the given fieldReference. * @@ -13,7 +37,7 @@ public class EvaluationOperators { public static EvaluationOperatorFactory valueOf(String fieldReference) { return new EvaluationOperatorFactory(fieldReference); } - + /** * Take the value resulting from the given {@link AggregationExpression}. * @@ -23,12 +47,12 @@ public static EvaluationOperatorFactory valueOf(String fieldReference) { public static EvaluationOperatorFactory valueOf(AggregationExpression expression) { return new EvaluationOperatorFactory(expression); } - + public static class EvaluationOperatorFactory { - + private final String fieldReference; private final AggregationExpression expression; - + /** * Creates new {@link EvaluationOperatorFactory} for given {@literal fieldReference}. * @@ -41,7 +65,6 @@ public EvaluationOperatorFactory(String fieldReference) { this.expression = null; } - /** * Creates new {@link EvaluationOperatorFactory} for given {@link AggregationExpression}. * @@ -53,7 +76,7 @@ public EvaluationOperatorFactory(AggregationExpression expression) { this.fieldReference = null; this.expression = expression; } - + /** * Creates new {@link AggregationExpression} that is a valid aggregation expression. * @@ -62,8 +85,10 @@ public EvaluationOperatorFactory(AggregationExpression expression) { public Expr expr() { return usesFieldRef() ? Expr.valueOf(fieldReference) : Expr.valueOf(expression); } - - + + /** + * Allows the use of aggregation expressions within the query language. + */ public static class Expr extends AbstractAggregationExpression { private Expr(Object value) { @@ -99,8 +124,29 @@ public static Expr valueOf(AggregationExpression expression) { return new Expr(expression); } + /** + * Creates {@code $expr} as {@link CriteriaDefinition}. + * + * @return the {@link CriteriaDefinition} from this expression. + */ + public CriteriaDefinition toCriteriaDefinition(AggregationOperationContext context) { + + Document criteriaObject = toDocument(context); + + return new CriteriaDefinition() { + @Override + public Document getCriteriaObject() { + return criteriaObject; + } + + @Override + public String getKey() { + return getMongoMethod(); + } + }; + } } - + private boolean usesFieldRef() { return fieldReference != null; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index c2796aaa03..c3d1f366ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -16,7 +16,7 @@ package org.springframework.data.mongodb.core.aggregation; import org.bson.Document; -import org.springframework.data.mongodb.core.aggregation.EvaluationOperators.EvaluationOperatorFactory.Expr; + import org.springframework.data.mongodb.core.query.CriteriaDefinition; import org.springframework.util.Assert; @@ -30,6 +30,7 @@ * @author Sebastian Herold * @author Thomas Darimont * @author Oliver Gierke + * @author Divya Srivastava * @since 1.3 * @see MongoDB Aggregation Framework: * $match @@ -38,15 +39,7 @@ public class MatchOperation implements AggregationOperation { private final CriteriaDefinition criteriaDefinition; private final AggregationExpression expression; - - /** - * Creates a new {@link MatchOperation} - */ - public MatchOperation() { - this.criteriaDefinition = null; - this.expression = null; - } - + /** * Creates a new {@link MatchOperation} for the given {@link CriteriaDefinition}. * @@ -55,41 +48,34 @@ public MatchOperation() { public MatchOperation(CriteriaDefinition criteriaDefinition) { Assert.notNull(criteriaDefinition, "Criteria must not be null!"); + this.criteriaDefinition = criteriaDefinition; this.expression = null; } - - /** - * Creates a new {@link MatchOperation} for the given {@link Expression}. - * - * @param criteriaDefinition must not be {@literal null}. - */ - private MatchOperation(Expr expression) { - Assert.notNull(expression, "Expression must not be null!"); - this.criteriaDefinition = null; - this.expression = expression; - } - + /** * Creates a new {@link MatchOperation} for the given {@link AggregationExpression}. * * @param expression must not be {@literal null}. + * @since 3.3 */ - public MatchOperation withValueOf(AggregationExpression expression) { + public MatchOperation(AggregationExpression expression) { + Assert.notNull(expression, "Expression must not be null!"); - return new MatchOperation(EvaluationOperators.valueOf(expression).expr()); + + this.criteriaDefinition = null; + this.expression = expression; } - + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) */ @Override public Document toDocument(AggregationOperationContext context) { - if(expression != null) { - return new Document(getOperator(), expression.toDocument()); - } - return new Document(getOperator(), context.getMappedObject(criteriaDefinition.getCriteriaObject())); + + return new Document(getOperator(), + context.getMappedObject(expression != null ? expression.toDocument() : criteriaDefinition.getCriteriaObject())); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperatorsUnitTests.java new file mode 100644 index 0000000000..67f5093b8f --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/EvaluationOperatorsUnitTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021 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 + * + * https://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.aggregation; + +import static org.springframework.data.mongodb.test.util.Assertions.*; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link EvaluationOperators}. + * + * @author Mark Paluch + */ +class EvaluationOperatorsUnitTests { + + @Test // GH-3790 + void shouldRenderExprCorrectly() { + + assertThat(EvaluationOperators.valueOf("foo").expr().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $expr: \"$foo\" }"); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java index 04d3824de1..ec3decb7a8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/MatchOperationUnitTests.java @@ -1,26 +1,23 @@ package org.springframework.data.mongodb.core.aggregation; -import static org.assertj.core.api.Assertions.*; -import org.bson.Document; +import static org.springframework.data.mongodb.test.util.Assertions.*; + import org.junit.jupiter.api.Test; +/** + * Unit tests for {@link MatchOperation}. + * + * @author Divya Srivastava + */ class MatchOperationUnitTests { - - @Test // DATAMONGO - 3729 - public void shouldRenderStdDevPopCorrectly() { - MatchOperation operation = Aggregation.match().withValueOf(ArithmeticOperators.valueOf("quiz").stdDevPop()); - assertThat(operation.toDocument(Aggregation.DEFAULT_CONTEXT)). - isEqualTo(Document.parse("{ $match: { \"$expr\" : { \"$stdDevPop\" : \"$quiz\" } } } ")); - - } - - @Test // DATAMONGO - 3729 - public void shouldRenderStdDevSampCorrectly() { - MatchOperation operation = Aggregation.match().withValueOf(ArithmeticOperators.valueOf("quiz").stdDevSamp()); + + @Test // GH-3790 + void matchShouldRenderCorrectly() { + + MatchOperation operation = Aggregation.match(ArithmeticOperators.valueOf("quiz").stdDevPop()); assertThat(operation.toDocument(Aggregation.DEFAULT_CONTEXT)). - isEqualTo(Document.parse("{ $match: { \"$expr\" : { \"$stdDevSamp\" : \"$quiz\" } } } ")); - + isEqualTo("{ $match: { \"$stdDevPop\" : \"$quiz\" } } "); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java index e97e1ff018..9fbc36586f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceRootOperationUnitTests.java @@ -27,20 +27,20 @@ * * @author Mark Paluch */ -public class ReplaceRootOperationUnitTests { +class ReplaceRootOperationUnitTests { @Test // DATAMONGO-1550 - public void rejectsNullField() { + void rejectsNullField() { assertThatIllegalArgumentException().isThrownBy(() -> new ReplaceRootOperation((Field) null)); } @Test // DATAMONGO-1550 - public void rejectsNullExpression() { + void rejectsNullExpression() { assertThatIllegalArgumentException().isThrownBy(() -> new ReplaceRootOperation((AggregationExpression) null)); } @Test // DATAMONGO-1550 - public void shouldRenderCorrectly() { + void shouldRenderCorrectly() { ReplaceRootOperation operation = ReplaceRootDocumentOperation.builder() .withDocument(new Document("hello", "world")); @@ -50,7 +50,7 @@ public void shouldRenderCorrectly() { } @Test // DATAMONGO-1550 - public void shouldRenderExpressionCorrectly() { + void shouldRenderExpressionCorrectly() { ReplaceRootOperation operation = new ReplaceRootOperation(VariableOperators // .mapItemsOf("array") // @@ -64,7 +64,7 @@ public void shouldRenderExpressionCorrectly() { } @Test // DATAMONGO-1550 - public void shouldComposeDocument() { + void shouldComposeDocument() { ReplaceRootOperation operation = ReplaceRootDocumentOperation.builder().withDocument() // .andValue("value").as("key") // @@ -77,7 +77,7 @@ public void shouldComposeDocument() { } @Test // DATAMONGO-1550 - public void shouldComposeSubDocument() { + void shouldComposeSubDocument() { Document partialReplacement = new Document("key", "override").append("key2", "value2"); @@ -92,7 +92,7 @@ public void shouldComposeSubDocument() { } @Test // DATAMONGO-1550 - public void shouldNotExposeFields() { + void shouldNotExposeFields() { ReplaceRootOperation operation = new ReplaceRootOperation(Fields.field("field")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java index 8f8b5c9dd1..d1a21a254c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ReplaceWithOperationUnitTests.java @@ -25,15 +25,15 @@ * * @author Christoph Strobl */ -public class ReplaceWithOperationUnitTests { +class ReplaceWithOperationUnitTests { @Test // DATAMONGO-2331 - public void rejectsNullField() { + void rejectsNullField() { assertThatIllegalArgumentException().isThrownBy(() -> new ReplaceWithOperation(null)); } @Test // DATAMONGO-2331 - public void shouldRenderValueCorrectly() { + void shouldRenderValueCorrectly() { ReplaceWithOperation operation = ReplaceWithOperation.replaceWithValue(new Document("hello", "world")); Document dbObject = operation.toDocument(Aggregation.DEFAULT_CONTEXT); @@ -42,7 +42,7 @@ public void shouldRenderValueCorrectly() { } @Test // DATAMONGO-2331 - public void shouldRenderExpressionCorrectly() { + void shouldRenderExpressionCorrectly() { ReplaceWithOperation operation = ReplaceWithOperation.replaceWithValueOf(VariableOperators // .mapItemsOf("array") // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 808263697a..46db6e7d6a 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -43,6 +43,9 @@ import org.springframework.data.geo.Point; import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.Person; +import org.springframework.data.mongodb.core.aggregation.ConditionalOperators; +import org.springframework.data.mongodb.core.aggregation.EvaluationOperators; +import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.geo.GeoJsonPolygon; import org.springframework.data.mongodb.core.mapping.DBRef; @@ -1330,6 +1333,21 @@ void allowsUsingFieldPathsForPropertiesHavingCustomConversionRegistered() { assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class))).isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive")); } + @Test // GH-3790 + void shouldAcceptExprAsCriteriaDefinition() { + + EvaluationOperators.EvaluationOperatorFactory.Expr expr = EvaluationOperators + .valueOf(ConditionalOperators.ifNull("customizedField").then(true)).expr(); + + Query query = query( + expr.toCriteriaDefinition(new TypeBasedAggregationOperationContext(EmbeddedClass.class, context, mapper))); + + org.bson.Document mappedQuery = mapper.getMappedObject(query.getQueryObject(), + context.getRequiredPersistentEntity(EmbeddedClass.class)); + + assertThat(mappedQuery).isEqualTo("{ $expr : { $ifNull : [\"$fancy_custom_name\", true] } }"); + } + @Test // GH-3668 void mapStringIdFieldProjection() { From ffceed8da96bb2b83206a87440bebc8d30687c10 Mon Sep 17 00:00:00 2001 From: divya srivastava Date: Sun, 29 Aug 2021 19:07:14 +0530 Subject: [PATCH 0526/1381] Add support for `$atan`, `$atan2` and `$atanh` aggregation operators. Closes #3709 Original pull request: #3794. --- .../core/aggregation/ArithmeticOperators.java | 258 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 3 + .../data/mongodb/util/RegexFlags.java | 2 +- .../ArithmeticOperatorsUnitTests.java | 22 ++ .../SpelExpressionTransformerUnitTests.java | 15 + 5 files changed, 299 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 8fe3d9120c..bf10488f99 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -790,6 +790,68 @@ public Cosh cosh(AngularUnit unit) { public Tan tan() { return tan(AngularUnit.RADIANS); } + + /** + * Creates new {@link AggregationExpression} that calculates the inverse tangent of a numeric value. + * + * @return new instance of {@link ATan}. + */ + public ATan atan() { + return usesFieldRef() ? ATan.atanOf(fieldReference) : ATan.atanOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value + * divided by the given numeric value in the argument. + * + * @param the numeric value + * @return new instance of {@link ATan2}. + */ + public ATan2 atan2(Number value) { + + Assert.notNull(value, "Value must not be null!"); + return createATan2().atan2of(value); + } + + /** + * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value + * divided by the given field reference in the argument. + * + * @param the numeric value + * @return new instance of {@link ATan2}. + */ + public ATan2 atan2(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return createATan2().atan2of(fieldReference); + } + + /** + * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value + * divided by the given {@link AggregationExpression} in the argument. + * + * @param the numeric value + * @return new instance of {@link ATan2}. + */ + public ATan2 atan2(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + return createATan2().atan2of(expression); + } + + private ATan2 createATan2() { + + return usesFieldRef() ? ATan2.valueOf(fieldReference) : ATan2.valueOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that calculates the inverse hyperbolic tangent of a numeric value. + * + * @return new instance of {@link ATanh}. + */ + public ATanh atanh() { + return usesFieldRef() ? ATanh.atanhOf(fieldReference) : ATanh.atanhOf(expression); + } /** * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value in the given @@ -2579,6 +2641,148 @@ protected String getMongoMethod() { return "$tan"; } } + + + /** + * An {@link AggregationExpression expression} that calculates the inverse tangent of a value. + * + */ + public static class ATan extends AbstractAggregationExpression { + + private ATan(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of a value. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link ATan}. + */ + public static ATan atanOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new ATan(Fields.field(fieldReference)); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of a value. + *

      + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link ATan}. + */ + public static ATan atanOf(AggregationExpression expression) { + return new ATan(expression); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of a value. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link ATan}. + */ + public static ATan atanof(Number value) { + return new ATan(value); + } + + @Override + protected String getMongoMethod() { + return "$atan"; + } + } + + /** + * An {@link AggregationExpression expression} that calculates the inverse + * tangent of y / x, where y and x are the first and second values passed to the + * expression respectively. + * + */ + public static class ATan2 extends AbstractAggregationExpression { + + private ATan2(List value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * tangent of of y / x, where y and x are the first and second values passed to + * the expression respectively. + * + * @param fieldReference the name of the {@link Field field} that resolves to a + * numeric value. + * @return new instance of {@link ATan2}. + */ + public static ATan2 valueOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new ATan2(asFields(fieldReference)); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * tangent of of y / x, where y and x are the first and second values passed to + * the expression respectively. + * + * @param expression the {@link AggregationExpression expression} that resolves + * to a numeric value. + * @return new instance of {@link ATan2}. + */ + public static ATan2 valueOf(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + return new ATan2((Collections.singletonList(expression))); + } + + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * tangent of of y / x, where y and x are the first and second values passed to + * the expression respectively. + * + * @param value anything ({@link Field field}, {@link AggregationExpression + * expression}, ...) that resolves to a numeric value. + * @return new instance of {@link ATan2}. + */ + public ATan2 atan2of(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new ATan2(append(Fields.field(fieldReference))); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in + * {@link AngularUnit#RADIANS}. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link ATan2}. + */ + public ATan2 atan2of(AggregationExpression expression) { + + Assert.notNull(expression, "Expression must not be null!"); + return new ATan2(append(expression)); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * tangent of of y / x, where y and x are the first and second values passed to + * the expression respectively. + * + * @param value of type {@link Number} + * @return new instance of {@link ATan2}. + */ + public ATan2 atan2of(Number value) { + + return new ATan2(append(value)); + } + + @Override + protected String getMongoMethod() { + return "$atan2"; + } + } /** * An {@link AggregationExpression expression} that calculates the hyperbolic tangent of a value that is measured in @@ -2684,6 +2888,60 @@ protected String getMongoMethod() { return "$tanh"; } } + + /** + * An {@link AggregationExpression expression} that calculates the inverse + * hyperbolic tangent of a value + * + */ + public static class ATanh extends AbstractAggregationExpression { + + private ATanh(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * hyperbolic tangent of a value. + * + * @param fieldReference the name of the {@link Field field} that resolves to a + * numeric value. + * @return new instance of {@link ATanh}. + */ + public static ATanh atanhOf(String fieldReference) { + return new ATanh(Fields.field(fieldReference)); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * hyperbolic tangent of a value. + *

      + * + * @param expression the {@link AggregationExpression expression} that resolves + * to a numeric value. + * @return new instance of {@link ATanh}. + */ + public static ATanh atanhOf(AggregationExpression expression) { + return new ATanh(expression); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse + * hyperbolic tangent of a value. + * + * @param value anything ({@link Field field}, {@link AggregationExpression + * expression}, ...) that resolves to a numeric value. + * @return new instance of {@link ATanh}. + */ + public static ATanh atanhof(Object value) { + return new ATanh(value); + } + + @Override + protected String getMongoMethod() { + return "$atanh"; + } + } /** * {@link Rand} returns a floating value between 0 and 1. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 0fbfe51f09..0f27c463e2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -100,6 +100,9 @@ public class MethodReferenceNode extends ExpressionNode { map.put("tan", singleArgRef().forOperator("$tan")); map.put("tanh", singleArgRef().forOperator("$tanh")); map.put("rand", emptyRef().forOperator("$rand")); + map.put("atan", singleArgRef().forOperator("$atan")); + map.put("atan2", arrayArgRef().forOperator("$atan2")); + map.put("atanh", singleArgRef().forOperator("$atanh")); // STRING OPERATORS map.put("concat", arrayArgRef().forOperator("$concat")); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java index dfee94954c..ba6531e93c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/RegexFlags.java @@ -113,4 +113,4 @@ public static int toRegexFlag(char c) { return flag; } -} +} \ No newline at end of file diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 02f76d5c10..8a52a8a2f5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -166,6 +166,28 @@ void rendersTanhWithValueInDegrees() { assertThat(valueOf("angle").tanh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo("{ $tanh : { $degreesToRadians : \"$angle\" } }"); } + + @Test // DATAMONGO - 3709 + void rendersATan() { + + assertThat(valueOf("field").atan().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $atan : \"$field\" }"); + } + + @Test // DATAMONGO - 3709 + void rendersATan2() { + + assertThat(valueOf("field1").atan2("field2").toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $atan2 : [ \"$field1\" , \"$field2\" ] }"); + } + + @Test // DATAMONGO - 3709 + void rendersATanh() { + + assertThat(valueOf("field").atanh().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $atanh : \"$field\" }"); + } + @Test // GH-3724 void rendersRand() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index e92ea38336..c9ba9c12e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1098,6 +1098,21 @@ void shouldRenderTan() { void shouldRenderTanh() { assertThat(transform("tanh(angle)")).isEqualTo("{ \"$tanh\" : \"$angle\"}"); } + + @Test // DATAMONGO - 3709 + void shouldRenderATan() { + assertThat(transform("atan(number)")).isEqualTo("{ \"$atan\" : \"$number\"}"); + } + + @Test // DATAMONGO - 3709 + void shouldRenderATan2() { + assertThat(transform("atan2(number1,number2)")).isEqualTo("{ \"$atan2\" : [ \"$number1\" , \"$number2\" ] }"); + } + + @Test // DATAMONGO - 3709 + void shouldRenderATanh() { + assertThat(transform("atanh(number)")).isEqualTo("{ \"$atanh\" : \"$number\"}"); + } @Test // GH-3713 void shouldRenderDateAdd() { From 8af904b81fb190e6b9663629daff76b11ed8028f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 6 Sep 2021 15:46:07 +0200 Subject: [PATCH 0527/1381] Polishing. Add author and since tags. Tweak Javadoc format. See #3709 Original pull request: #3794. --- .../core/aggregation/ArithmeticOperators.java | 155 +++++++++--------- .../ArithmeticOperatorsUnitTests.java | 46 +++--- .../reference/aggregation-framework.adoc | 2 +- 3 files changed, 93 insertions(+), 110 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index bf10488f99..d21d985882 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -717,7 +717,7 @@ public Sin sin(AngularUnit unit) { * Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in * {@link AngularUnit#RADIANS radians}. * - * @return new instance of {@link Sin}. + * @return new instance of {@link Sinh}. * @since 3.3 */ public Sinh sinh() { @@ -728,7 +728,7 @@ public Sinh sinh() { * Creates new {@link AggregationExpression} that calculates the sine of a numeric value. * * @param unit the unit of measure. - * @return new instance of {@link Sin}. + * @return new instance of {@link Sinh}. * @since 3.3 */ public Sinh sinh(AngularUnit unit) { @@ -739,7 +739,7 @@ public Sinh sinh(AngularUnit unit) { * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value given in * {@link AngularUnit#RADIANS radians}. * - * @return new instance of {@link Sin}. + * @return new instance of {@link Cos}. * @since 3.3 */ public Cos cos() { @@ -751,7 +751,7 @@ public Cos cos() { * {@link AngularUnit unit}. * * @param unit the unit of measure. - * @return new instance of {@link Sin}. + * @return new instance of {@link Cos}. * @since 3.3 */ public Cos cos(AngularUnit unit) { @@ -762,7 +762,7 @@ public Cos cos(AngularUnit unit) { * Creates new {@link AggregationExpression} that calculates the hyperbolic cosine of a numeric value given in * {@link AngularUnit#RADIANS radians}. * - * @return new instance of {@link Sin}. + * @return new instance of {@link Cosh}. * @since 3.3 */ public Cosh cosh() { @@ -773,7 +773,7 @@ public Cosh cosh() { * Creates new {@link AggregationExpression} that calculates the hyperbolic cosine of a numeric value. * * @param unit the unit of measure. - * @return new instance of {@link Sin}. + * @return new instance of {@link Cosh}. * @since 3.3 */ public Cosh cosh(AngularUnit unit) { @@ -784,70 +784,75 @@ public Cosh cosh(AngularUnit unit) { * Creates new {@link AggregationExpression} that calculates the tangent of a numeric value given in * {@link AngularUnit#RADIANS radians}. * - * @return new instance of {@link Sin}. + * @return new instance of {@link Tan}. * @since 3.3 */ public Tan tan() { return tan(AngularUnit.RADIANS); } - + /** * Creates new {@link AggregationExpression} that calculates the inverse tangent of a numeric value. * * @return new instance of {@link ATan}. + * @since 3.3 */ public ATan atan() { return usesFieldRef() ? ATan.atanOf(fieldReference) : ATan.atanOf(expression); } - + /** - * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value - * divided by the given numeric value in the argument. + * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value divided by + * the given numeric value in the argument. * - * @param the numeric value + * @param the numeric value * @return new instance of {@link ATan2}. + * @since 3.3 */ public ATan2 atan2(Number value) { - + Assert.notNull(value, "Value must not be null!"); return createATan2().atan2of(value); } - + /** - * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value - * divided by the given field reference in the argument. + * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value divided by + * the given field reference in the argument. * - * @param the numeric value + * @param the numeric value * @return new instance of {@link ATan2}. + * @since 3.3 */ public ATan2 atan2(String fieldReference) { - + Assert.notNull(fieldReference, "FieldReference must not be null!"); return createATan2().atan2of(fieldReference); } - + /** - * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value - * divided by the given {@link AggregationExpression} in the argument. + * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value divided by + * the given {@link AggregationExpression} in the argument. * - * @param the numeric value + * @param the numeric value * @return new instance of {@link ATan2}. + * @since 3.3 */ public ATan2 atan2(AggregationExpression expression) { - + Assert.notNull(expression, "Expression must not be null!"); return createATan2().atan2of(expression); } - + private ATan2 createATan2() { - + return usesFieldRef() ? ATan2.valueOf(fieldReference) : ATan2.valueOf(expression); } - + /** * Creates new {@link AggregationExpression} that calculates the inverse hyperbolic tangent of a numeric value. * * @return new instance of {@link ATanh}. + * @since 3.3 */ public ATanh atanh() { return usesFieldRef() ? ATanh.atanhOf(fieldReference) : ATanh.atanhOf(expression); @@ -858,7 +863,7 @@ public ATanh atanh() { * {@link AngularUnit unit}. * * @param unit the unit of measure. - * @return new instance of {@link Sin}. + * @return new instance of {@link Tan}. * @since 3.3 */ public Tan tan(AngularUnit unit) { @@ -869,7 +874,7 @@ public Tan tan(AngularUnit unit) { * Creates new {@link AggregationExpression} that calculates the hyperbolic tangent of a numeric value given in * {@link AngularUnit#RADIANS radians}. * - * @return new instance of {@link Sin}. + * @return new instance of {@link Tan}. * @since 3.3 */ public Tanh tanh() { @@ -880,7 +885,7 @@ public Tanh tanh() { * Creates new {@link AggregationExpression} that calculates the hyperbolic tangent of a numeric value. * * @param unit the unit of measure. - * @return new instance of {@link Sin}. + * @return new instance of {@link Tanh}. * @since 3.3 */ public Tanh tanh(AngularUnit unit) { @@ -2357,8 +2362,6 @@ private Cos(Object value) { * { $cos : { $degreesToRadians : "$angle" } } * * - * . - * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Cos}. */ @@ -2470,8 +2473,6 @@ public static Cosh coshOf(String fieldReference) { * { $cosh : { $degreesToRadians : "$angle" } } * * - * . - * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Cosh}. @@ -2563,8 +2564,6 @@ private Tan(Object value) { * { $tan : { $degreesToRadians : "$angle" } } * * - * . - * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link Tan}. */ @@ -2641,11 +2640,12 @@ protected String getMongoMethod() { return "$tan"; } } - - + /** * An {@link AggregationExpression expression} that calculates the inverse tangent of a value. * + * @author Divya Srivastava + * @since 3.3 */ public static class ATan extends AbstractAggregationExpression { @@ -2660,14 +2660,13 @@ private ATan(Object value) { * @return new instance of {@link ATan}. */ public static ATan atanOf(String fieldReference) { - + Assert.notNull(fieldReference, "FieldReference must not be null!"); return new ATan(Fields.field(fieldReference)); } /** * Creates a new {@link AggregationExpression} that calculates the inverse tangent of a value. - *

      * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ATan}. @@ -2683,7 +2682,7 @@ public static ATan atanOf(AggregationExpression expression) { * numeric value. * @return new instance of {@link ATan}. */ - public static ATan atanof(Number value) { + public static ATan atanOf(Number value) { return new ATan(value); } @@ -2692,26 +2691,25 @@ protected String getMongoMethod() { return "$atan"; } } - + /** - * An {@link AggregationExpression expression} that calculates the inverse - * tangent of y / x, where y and x are the first and second values passed to the - * expression respectively. + * An {@link AggregationExpression expression} that calculates the inverse tangent of y / x, where y and x are the + * first and second values passed to the expression respectively. * + * @author Divya Srivastava + * @since 3.3 */ public static class ATan2 extends AbstractAggregationExpression { - + private ATan2(List value) { super(value); } /** - * Creates a new {@link AggregationExpression} that calculates the inverse - * tangent of of y / x, where y and x are the first and second values passed to - * the expression respectively. - * - * @param fieldReference the name of the {@link Field field} that resolves to a - * numeric value. + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of of y / x, where y and x are + * the first and second values passed to the expression respectively. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @return new instance of {@link ATan2}. */ public static ATan2 valueOf(String fieldReference) { @@ -2721,12 +2719,10 @@ public static ATan2 valueOf(String fieldReference) { } /** - * Creates a new {@link AggregationExpression} that calculates the inverse - * tangent of of y / x, where y and x are the first and second values passed to - * the expression respectively. - * - * @param expression the {@link AggregationExpression expression} that resolves - * to a numeric value. + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of of y / x, where y and x are + * the first and second values passed to the expression respectively. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ATan2}. */ public static ATan2 valueOf(AggregationExpression expression) { @@ -2737,12 +2733,11 @@ public static ATan2 valueOf(AggregationExpression expression) { /** - * Creates a new {@link AggregationExpression} that calculates the inverse - * tangent of of y / x, where y and x are the first and second values passed to - * the expression respectively. - * - * @param value anything ({@link Field field}, {@link AggregationExpression - * expression}, ...) that resolves to a numeric value. + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of of y / x, where y and x are + * the first and second values passed to the expression respectively. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. * @return new instance of {@link ATan2}. */ public ATan2 atan2of(String fieldReference) { @@ -2750,7 +2745,7 @@ public ATan2 atan2of(String fieldReference) { Assert.notNull(fieldReference, "FieldReference must not be null!"); return new ATan2(append(Fields.field(fieldReference))); } - + /** * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in * {@link AngularUnit#RADIANS}. @@ -2760,21 +2755,20 @@ public ATan2 atan2of(String fieldReference) { * @return new instance of {@link ATan2}. */ public ATan2 atan2of(AggregationExpression expression) { - + Assert.notNull(expression, "Expression must not be null!"); return new ATan2(append(expression)); } - + /** - * Creates a new {@link AggregationExpression} that calculates the inverse - * tangent of of y / x, where y and x are the first and second values passed to - * the expression respectively. - * + * Creates a new {@link AggregationExpression} that calculates the inverse tangent of of y / x, where y and x are + * the first and second values passed to the expression respectively. + * * @param value of type {@link Number} * @return new instance of {@link ATan2}. */ public ATan2 atan2of(Number value) { - + return new ATan2(append(value)); } @@ -2818,8 +2812,6 @@ public static Tanh tanhOf(String fieldReference) { * { $tanh : { $degreesToRadians : "$angle" } } * * - * . - * * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. * @param unit the unit of measure used by the value of the given field. * @return new instance of {@link Tanh}. @@ -2888,11 +2880,12 @@ protected String getMongoMethod() { return "$tanh"; } } - + /** - * An {@link AggregationExpression expression} that calculates the inverse - * hyperbolic tangent of a value + * An {@link AggregationExpression expression} that calculates the inverse hyperbolic tangent of a value * + * @author Divya Srivastava + * @since 3.3 */ public static class ATanh extends AbstractAggregationExpression { @@ -2913,12 +2906,10 @@ public static ATanh atanhOf(String fieldReference) { } /** - * Creates a new {@link AggregationExpression} that calculates the inverse - * hyperbolic tangent of a value. + * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic tangent of a value. *

      - * - * @param expression the {@link AggregationExpression expression} that resolves - * to a numeric value. + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ATanh}. */ public static ATanh atanhOf(AggregationExpression expression) { @@ -2933,7 +2924,7 @@ public static ATanh atanhOf(AggregationExpression expression) { * expression}, ...) that resolves to a numeric value. * @return new instance of {@link ATanh}. */ - public static ATanh atanhof(Object value) { + public static ATanh atanhOf(Object value) { return new ATanh(value); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 8a52a8a2f5..84d228f75e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -30,6 +30,7 @@ * @author Christoph Strobl * @author Mark Paluch * @author Mushtaq Ahmed + * @author Divya Srivastava */ class ArithmeticOperatorsUnitTests { @@ -86,8 +87,7 @@ void rendersIntegralWithUnit() { @Test // GH-3728 void rendersSin() { - assertThat(valueOf("angle").sin().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $sin : \"$angle\" }"); + assertThat(valueOf("angle").sin().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $sin : \"$angle\" }"); } @Test // GH-3728 @@ -100,8 +100,7 @@ void rendersSinWithValueInDegrees() { @Test // GH-3728 void rendersSinh() { - assertThat(valueOf("angle").sinh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $sinh : \"$angle\" }"); + assertThat(valueOf("angle").sinh().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $sinh : \"$angle\" }"); } @Test // GH-3728 @@ -114,8 +113,7 @@ void rendersSinhWithValueInDegrees() { @Test // GH-3710 void rendersCos() { - assertThat(valueOf("angle").cos().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $cos : \"$angle\" }"); + assertThat(valueOf("angle").cos().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $cos : \"$angle\" }"); } @Test // GH-3710 @@ -128,8 +126,7 @@ void rendersCosWithValueInDegrees() { @Test // GH-3710 void rendersCosh() { - assertThat(valueOf("angle").cosh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $cosh : \"$angle\" }"); + assertThat(valueOf("angle").cosh().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $cosh : \"$angle\" }"); } @Test // GH-3710 @@ -142,8 +139,7 @@ void rendersCoshWithValueInDegrees() { @Test // GH-3730 void rendersTan() { - assertThat(valueOf("angle").tan().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $tan : \"$angle\" }"); + assertThat(valueOf("angle").tan().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $tan : \"$angle\" }"); } @Test // GH-3730 @@ -156,8 +152,7 @@ void rendersTanWithValueInDegrees() { @Test // GH-3730 void rendersTanh() { - assertThat(valueOf("angle").tanh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $tanh : \"$angle\" }"); + assertThat(valueOf("angle").tanh().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $tanh : \"$angle\" }"); } @Test // GH-3730 @@ -166,28 +161,25 @@ void rendersTanhWithValueInDegrees() { assertThat(valueOf("angle").tanh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo("{ $tanh : { $degreesToRadians : \"$angle\" } }"); } - - @Test // DATAMONGO - 3709 + + @Test // GH-3709 void rendersATan() { - - assertThat(valueOf("field").atan().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $atan : \"$field\" }"); + + assertThat(valueOf("field").atan().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $atan : \"$field\" }"); } - - @Test // DATAMONGO - 3709 + + @Test // GH-3709 void rendersATan2() { - + assertThat(valueOf("field1").atan2("field2").toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $atan2 : [ \"$field1\" , \"$field2\" ] }"); + .isEqualTo("{ $atan2 : [ \"$field1\" , \"$field2\" ] }"); } - - @Test // DATAMONGO - 3709 + + @Test // GH-3709 void rendersATanh() { - - assertThat(valueOf("field").atanh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $atanh : \"$field\" }"); - } + assertThat(valueOf("field").atanh().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $atanh : \"$field\" }"); + } @Test // GH-3724 void rendersRand() { diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index 75ed415096..387a0acf65 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -85,7 +85,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (+++*+++ via `plus`), `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` +| `abs`, `add` (+++*+++ via `plus`), `atan`, `atan2`, `atanh`, `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `regexFind`, `regexFindAll`, `regexMatch`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` From 59d0042d13a8af35a84a48f992c190bed00006b0 Mon Sep 17 00:00:00 2001 From: divyajnu08 Date: Wed, 1 Sep 2021 13:02:43 +0530 Subject: [PATCH 0528/1381] Add support for `$asin` and `$asinh` aggregation operators. Closes #3708 Original pull request: #3796. --- .../core/aggregation/ArithmeticOperators.java | 116 ++++++++++++++++++ .../core/spel/MethodReferenceNode.java | 2 + .../ArithmeticOperatorsUnitTests.java | 14 +++ .../SpelExpressionTransformerUnitTests.java | 10 ++ 4 files changed, 142 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index d21d985882..d865d57a7d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -735,6 +735,24 @@ public Sinh sinh(AngularUnit unit) { return usesFieldRef() ? Sinh.sinhOf(fieldReference, unit) : Sinh.sinhOf(expression, unit); } + /** + * Creates new {@link AggregationExpression} that calculates the inverse sine of a numeric value. + * + * @return new instance of {@link ASin}. + */ + public ASin asin() { + return usesFieldRef() ? ASin.asinOf(fieldReference) : ASin.asinOf(expression); + } + + /** + * Creates new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a numeric value. + * + * @return new instance of {@link ASinh}. + */ + public ASinh asinh() { + return usesFieldRef() ? ASinh.asinhOf(fieldReference) : ASinh.asinhOf(expression); + } + /** * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value given in * {@link AngularUnit#RADIANS radians}. @@ -2339,6 +2357,104 @@ protected String getMongoMethod() { return "$sinh"; } } + + /** + * An {@link AggregationExpression expression} that calculates the inverse sine of a value. + * + */ + public static class ASin extends AbstractAggregationExpression { + + private ASin(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse sine of a value. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link ASin}. + */ + public static ASin asinOf(String fieldReference) { + + Assert.notNull(fieldReference, "FieldReference must not be null!"); + return new ASin(Fields.field(fieldReference)); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse sine of a value. + *

      + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link ASin}. + */ + public static ASin asinOf(AggregationExpression expression) { + return new ASin(expression); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse sine of a value. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link ASin}. + */ + public static ASin asinOf(Number value) { + return new ASin(value); + } + + @Override + protected String getMongoMethod() { + return "$asin"; + } + } + + /** + * An {@link AggregationExpression expression} that calculates the inverse hyperbolic sine of a value + */ + public static class ASinh extends AbstractAggregationExpression { + + private ASinh(Object value) { + super(value); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a value. + * + * @param fieldReference the name of the {@link Field field} that resolves to a numeric value. + * @return new instance of {@link ASinh}. + */ + public static ASinh asinhOf(String fieldReference) { + return new ASinh(Fields.field(fieldReference)); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a value. + *

      + * + * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. + * @return new instance of {@link ASinh}. + */ + public static ASinh asinhOf(AggregationExpression expression) { + return new ASinh(expression); + } + + /** + * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a value. + * + * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a + * numeric value. + * @return new instance of {@link ASinh}. + */ + public static ASinh asinhOf(Object value) { + return new ASinh(value); + } + + @Override + protected String getMongoMethod() { + return "$asinh"; + } + } + /** * An {@link AggregationExpression expression} that calculates the cosine of a value that is measured in radians. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index 0f27c463e2..dc7a3cc982 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -95,6 +95,8 @@ public class MethodReferenceNode extends ExpressionNode { map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit")); map.put("sin", singleArgRef().forOperator("$sin")); map.put("sinh", singleArgRef().forOperator("$sinh")); + map.put("asin", singleArgRef().forOperator("$asin")); + map.put("asinh", singleArgRef().forOperator("$asinh")); map.put("cos", singleArgRef().forOperator("$cos")); map.put("cosh", singleArgRef().forOperator("$cosh")); map.put("tan", singleArgRef().forOperator("$tan")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index 84d228f75e..d0f50d2baf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -109,6 +109,20 @@ void rendersSinhWithValueInDegrees() { assertThat(valueOf("angle").sinh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo("{ $sinh : { $degreesToRadians : \"$angle\" } }"); } + + @Test // DATAMONGO - 3708 + void rendersASin() { + + assertThat(valueOf("field").asin().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $asin : \"$field\" }"); + } + + @Test // DATAMONGO - 3708 + void rendersASinh() { + + assertThat(valueOf("field").asinh().toDocument(Aggregation.DEFAULT_CONTEXT)) + .isEqualTo("{ $asinh : \"$field\" }"); + } @Test // GH-3710 void rendersCos() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index c9ba9c12e7..8077f604e5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1078,6 +1078,16 @@ void shouldRenderSin() { void shouldRenderSinh() { assertThat(transform("sinh(angle)")).isEqualTo("{ \"$sinh\" : \"$angle\"}"); } + + @Test // DATAMONGO-3708 + void shouldRenderASin() { + assertThat(transform("asin(number)")).isEqualTo("{ \"$asin\" : \"$number\"}"); + } + + @Test // DATAMONGO-3708 + void shouldRenderASinh() { + assertThat(transform("asinh(number)")).isEqualTo("{ \"$asinh\" : \"$number\"}"); + } @Test // GH-3710 void shouldRenderCos() { From dcf184888e88f1ae4a205df15b04b4b7d63a0880 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 7 Sep 2021 09:56:18 +0200 Subject: [PATCH 0529/1381] Polishing. Add since and author tags. Update reference docs. Fix format of ticket references in tests. See #3708 Original pull request: #3796. --- .../core/aggregation/ArithmeticOperators.java | 18 ++++++++++++------ .../ArithmeticOperatorsUnitTests.java | 16 ++++++---------- .../SpelExpressionTransformerUnitTests.java | 12 ++++++------ .../reference/aggregation-framework.adoc | 2 +- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index d865d57a7d..9c9132e679 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -739,20 +739,22 @@ public Sinh sinh(AngularUnit unit) { * Creates new {@link AggregationExpression} that calculates the inverse sine of a numeric value. * * @return new instance of {@link ASin}. + * @since 3.3 */ public ASin asin() { return usesFieldRef() ? ASin.asinOf(fieldReference) : ASin.asinOf(expression); } - + /** * Creates new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a numeric value. * * @return new instance of {@link ASinh}. + * @since 3.3 */ public ASinh asinh() { return usesFieldRef() ? ASinh.asinhOf(fieldReference) : ASinh.asinhOf(expression); } - + /** * Creates new {@link AggregationExpression} that calculates the cosine of a numeric value given in * {@link AngularUnit#RADIANS radians}. @@ -2357,10 +2359,12 @@ protected String getMongoMethod() { return "$sinh"; } } - + /** * An {@link AggregationExpression expression} that calculates the inverse sine of a value. * + * @author Divya Srivastava + * @since 3.3 */ public static class ASin extends AbstractAggregationExpression { @@ -2407,9 +2411,12 @@ protected String getMongoMethod() { return "$asin"; } } - + /** * An {@link AggregationExpression expression} that calculates the inverse hyperbolic sine of a value + * + * @author Divya Srivastava + * @since 3.3 */ public static class ASinh extends AbstractAggregationExpression { @@ -2430,7 +2437,7 @@ public static ASinh asinhOf(String fieldReference) { /** * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a value. *

      - * + * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ASinh}. */ @@ -2884,7 +2891,6 @@ public ATan2 atan2of(AggregationExpression expression) { * @return new instance of {@link ATan2}. */ public ATan2 atan2of(Number value) { - return new ATan2(append(value)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java index d0f50d2baf..ab3d1c2400 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java @@ -109,19 +109,15 @@ void rendersSinhWithValueInDegrees() { assertThat(valueOf("angle").sinh(AngularUnit.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT)) .isEqualTo("{ $sinh : { $degreesToRadians : \"$angle\" } }"); } - - @Test // DATAMONGO - 3708 - void rendersASin() { - assertThat(valueOf("field").asin().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $asin : \"$field\" }"); + @Test // GH-3708 + void rendersASin() { + assertThat(valueOf("field").asin().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $asin : \"$field\" }"); } - - @Test // DATAMONGO - 3708 - void rendersASinh() { - assertThat(valueOf("field").asinh().toDocument(Aggregation.DEFAULT_CONTEXT)) - .isEqualTo("{ $asinh : \"$field\" }"); + @Test // GH-3708 + void rendersASinh() { + assertThat(valueOf("field").asinh().toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo("{ $asinh : \"$field\" }"); } @Test // GH-3710 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index 8077f604e5..899e02a172 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -1078,13 +1078,13 @@ void shouldRenderSin() { void shouldRenderSinh() { assertThat(transform("sinh(angle)")).isEqualTo("{ \"$sinh\" : \"$angle\"}"); } - - @Test // DATAMONGO-3708 + + @Test // GH-3708 void shouldRenderASin() { assertThat(transform("asin(number)")).isEqualTo("{ \"$asin\" : \"$number\"}"); } - @Test // DATAMONGO-3708 + @Test // GH-3708 void shouldRenderASinh() { assertThat(transform("asinh(number)")).isEqualTo("{ \"$asinh\" : \"$number\"}"); } @@ -1108,17 +1108,17 @@ void shouldRenderTan() { void shouldRenderTanh() { assertThat(transform("tanh(angle)")).isEqualTo("{ \"$tanh\" : \"$angle\"}"); } - + @Test // DATAMONGO - 3709 void shouldRenderATan() { assertThat(transform("atan(number)")).isEqualTo("{ \"$atan\" : \"$number\"}"); } - + @Test // DATAMONGO - 3709 void shouldRenderATan2() { assertThat(transform("atan2(number1,number2)")).isEqualTo("{ \"$atan2\" : [ \"$number1\" , \"$number2\" ] }"); } - + @Test // DATAMONGO - 3709 void shouldRenderATanh() { assertThat(transform("atanh(number)")).isEqualTo("{ \"$atanh\" : \"$number\"}"); diff --git a/src/main/asciidoc/reference/aggregation-framework.adoc b/src/main/asciidoc/reference/aggregation-framework.adoc index 387a0acf65..45315cda36 100644 --- a/src/main/asciidoc/reference/aggregation-framework.adoc +++ b/src/main/asciidoc/reference/aggregation-framework.adoc @@ -85,7 +85,7 @@ At the time of this writing, we provide support for the following Aggregation Op | `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp` | Arithmetic Aggregation Operators -| `abs`, `add` (+++*+++ via `plus`), `atan`, `atan2`, `atanh`, `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` +| `abs`, `add` (+++*+++ via `plus`), `asin`, `asin`, `atan`, `atan2`, `atanh`, `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc` | String Aggregation Operators | `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `regexFind`, `regexFindAll`, `regexMatch`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim` From c8307d5a39d246a245db2866a55cee813edd888d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 7 Sep 2021 11:07:27 +0200 Subject: [PATCH 0530/1381] Allow one-to-many style lookups with via `@DocumentReference`. This commit adds support for relational style One-To-Many references using a combination of ReadonlyProperty and @DocumentReference. It allows to link types without explicitly storing the linking values within the document itself. @Document class Publisher { @Id ObjectId id; // ... @ReadOnlyProperty @DocumentReference(lookup="{'publisherId':?#{#self._id} }") List books; } Closes: #3798 Original pull request: #3802. --- .../convert/DefaultReferenceResolver.java | 2 +- .../core/convert/DocumentReferenceSource.java | 63 +++++++++++++++++++ .../core/convert/MappingMongoConverter.java | 16 +++-- .../core/convert/ReferenceLookupDelegate.java | 52 +++++++++++---- .../MongoTemplateDocumentReferenceTests.java | 48 ++++++++++++++ .../reference/document-references.adoc | 56 +++++++++++++++++ 6 files changed, 218 insertions(+), 19 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java index f801b8d990..62e713065f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultReferenceResolver.java @@ -108,6 +108,6 @@ private Object createLazyLoadingProxy(MongoPersistentProperty property, Object s ReferenceLookupDelegate referenceLookupDelegate, LookupFunction lookupFunction, MongoEntityReader entityReader) { return proxyFactory.createLazyLoadingProxy(property, it -> { return referenceLookupDelegate.readReference(it, source, lookupFunction, entityReader); - }, source); + }, source instanceof DocumentReferenceSource ? ((DocumentReferenceSource)source).getTargetSource() : source); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java new file mode 100644 index 0000000000..03e5eb0d5d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java @@ -0,0 +1,63 @@ +/* + * Copyright 2021 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 + * + * https://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.convert; + +import org.springframework.lang.Nullable; + +/** + * The source object to resolve document references upon. Encapsulates the actual source and the reference specific + * values. + * + * @author Christoph Strobl + * @since 3.3 + */ +public class DocumentReferenceSource { + + private final Object self; + + @Nullable private final Object targetSource; + + /** + * Create a new instance of {@link DocumentReferenceSource}. + * + * @param self the entire wrapper object holding references. Must not be {@literal null}. + * @param targetSource the reference value source. + */ + DocumentReferenceSource(Object self, @Nullable Object targetSource) { + + this.self = self; + this.targetSource = targetSource; + } + + /** + * Get the outer document. + * + * @return never {@literal null}. + */ + public Object getSelf() { + return self; + } + + /** + * Get the actual (property specific) reference value. + * + * @return can be {@literal null}. + */ + @Nullable + public Object getTargetSource() { + return targetSource; + } +} 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 a60c853c33..5a2c3e952a 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 @@ -38,7 +38,6 @@ 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; @@ -524,10 +523,6 @@ private void readAssociation(Association association, P MongoPersistentProperty property = association.getInverse(); Object value = documentAccessor.get(property); - if (value == null) { - return; - } - if (property.isDocumentReference() || (!property.isDbReference() && property.findAnnotation(Reference.class) != null)) { @@ -535,17 +530,26 @@ private void readAssociation(Association association, P if (conversionService.canConvert(DocumentPointer.class, property.getActualType())) { + if(value == null) { + return; + } + DocumentPointer pointer = () -> value; // collection like special treatment accessor.setProperty(property, conversionService.convert(pointer, property.getActualType())); } else { + accessor.setProperty(property, - dbRefResolver.resolveReference(property, value, referenceLookupDelegate, context::convert)); + dbRefResolver.resolveReference(property, new DocumentReferenceSource(documentAccessor.getDocument(), documentAccessor.get(property)), referenceLookupDelegate, context::convert)); } return; } + if (value == null) { + return; + } + DBRef dbref = value instanceof DBRef ? (DBRef) value : null; accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index 3ca730452f..e16f9024b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -87,17 +87,20 @@ public ReferenceLookupDelegate( * Read the reference expressed by the given property. * * @param property the reference defining property. Must not be {@literal null}. THe - * @param value the source value identifying to the referenced entity. Must not be {@literal null}. + * @param source the source value identifying to the referenced entity. Must not be {@literal null}. * @param lookupFunction to execute a lookup query. Must not be {@literal null}. * @param entityReader the callback to convert raw source values into actual domain types. Must not be * {@literal null}. * @return can be {@literal null}. */ @Nullable - public Object readReference(MongoPersistentProperty property, Object value, LookupFunction lookupFunction, + public Object readReference(MongoPersistentProperty property, Object source, LookupFunction lookupFunction, MongoEntityReader entityReader) { - DocumentReferenceQuery filter = computeFilter(property, value, spELContext); + Object value = source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getTargetSource() + : source; + + DocumentReferenceQuery filter = computeFilter(property, source, spELContext); ReferenceCollection referenceCollection = computeReferenceContext(property, value, spELContext); Iterable result = lookupFunction.apply(filter, referenceCollection); @@ -196,8 +199,16 @@ private T parseValueOrGet(String value, ParameterBindingContext bindingConte ParameterBindingContext bindingContext(MongoPersistentProperty property, Object source, SpELContext spELContext) { - return new ParameterBindingContext(valueProviderFor(source), spELContext.getParser(), + ValueProvider valueProvider; + if (source instanceof DocumentReferenceSource) { + valueProvider = valueProviderFor(((DocumentReferenceSource) source).getTargetSource()); + } else { + valueProvider = valueProviderFor(source); + } + + return new ParameterBindingContext(valueProvider, spELContext.getParser(), () -> evaluationContextFor(property, source, spELContext)); + } ValueProvider valueProviderFor(Object source) { @@ -212,9 +223,18 @@ ValueProvider valueProviderFor(Object source) { EvaluationContext evaluationContextFor(MongoPersistentProperty property, Object source, SpELContext spELContext) { - EvaluationContext ctx = spELContext.getEvaluationContext(source); - ctx.setVariable("target", source); - ctx.setVariable(property.getName(), source); + Object target = source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getTargetSource() + : source; + + if (target == null) { + target = new Document(); + } + + EvaluationContext ctx = spELContext.getEvaluationContext(target); + ctx.setVariable("target", target); + ctx.setVariable("self", + source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getSelf() : source); + ctx.setVariable(property.getName(), target); return ctx; } @@ -223,22 +243,30 @@ EvaluationContext evaluationContextFor(MongoPersistentProperty property, Object * Compute the query to retrieve linked documents. * * @param property must not be {@literal null}. - * @param value must not be {@literal null}. + * @param source must not be {@literal null}. * @param spELContext must not be {@literal null}. * @return never {@literal null}. */ @SuppressWarnings("unchecked") - DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object value, SpELContext spELContext) { + DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object source, SpELContext spELContext) { DocumentReference documentReference = property.isDocumentReference() ? property.getDocumentReference() : ReferenceEmulatingDocumentReference.INSTANCE; String lookup = documentReference.lookup(); - Document sort = parseValueOrGet(documentReference.sort(), bindingContext(property, value, spELContext), + Object value = source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getTargetSource() + : source; + + Document sort = parseValueOrGet(documentReference.sort(), bindingContext(property, source, spELContext), () -> new Document()); - if (property.isCollectionLike() && value instanceof Collection) { + if (property.isCollectionLike() && (value instanceof Collection || value == null)) { + + if (value == null) { + return new ListDocumentReferenceQuery(codec.decode(lookup, bindingContext(property, source, spELContext)), + sort); + } List ors = new ArrayList<>(); for (Object entry : (Collection) value) { @@ -263,7 +291,7 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object va return new MapDocumentReferenceQuery(new Document("$or", filterMap.values()), sort, filterMap); } - return new SingleDocumentReferenceQuery(codec.decode(lookup, bindingContext(property, value, spELContext)), sort); + return new SingleDocumentReferenceQuery(codec.decode(lookup, bindingContext(property, source, spELContext)), sort); } enum ReferenceEmulatingDocumentReference implements DocumentReference { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index d6bcc10e49..06d288d1f5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -39,6 +39,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.annotation.Reference; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils; @@ -1049,7 +1050,34 @@ void updateWhenUsingAtReferenceDirectly() { }); assertThat(target).containsEntry("publisher", "p-1"); + } + + @Test // GH-3798 + void allowsOneToMayStyleLookupsUsingSelfVariable() { + + OneToManyStyleBook book1 = new OneToManyStyleBook(); + book1.id = "id-1"; + book1.publisherId = "p-100"; + + OneToManyStyleBook book2 = new OneToManyStyleBook(); + book2.id = "id-2"; + book2.publisherId = "p-200"; + + OneToManyStyleBook book3 = new OneToManyStyleBook(); + book3.id = "id-3"; + book3.publisherId = "p-100"; + + template.save(book1); + template.save(book2); + template.save(book3); + OneToManyStylePublisher publisher = new OneToManyStylePublisher(); + publisher.id = "p-100"; + + template.save(publisher); + + OneToManyStylePublisher target = template.findOne(query(where("id").is(publisher.id)), OneToManyStylePublisher.class); + assertThat(target.books).containsExactlyInAnyOrder(book1, book3); } @Data @@ -1293,4 +1321,24 @@ static class UsingAtReference { @Reference // Publisher publisher; } + + @Data + static class OneToManyStyleBook { + + @Id + String id; + + private String publisherId; + } + + @Data + static class OneToManyStylePublisher { + + @Id + String id; + + @ReadOnlyProperty + @DocumentReference(lookup="{'publisherId':?#{#self._id} }") + List books; + } } diff --git a/src/main/asciidoc/reference/document-references.adoc b/src/main/asciidoc/reference/document-references.adoc index 885d2d6ade..23bc025e80 100644 --- a/src/main/asciidoc/reference/document-references.adoc +++ b/src/main/asciidoc/reference/document-references.adoc @@ -262,6 +262,62 @@ class Publisher { <2> The field value placeholders of the lookup query (like `acc`) is used to form the reference document. ==== +It is also possible to model relational style _One-To-Many_ references using a combination of `@ReadonlyProperty` and `@DocumentReference`. +This approach allows to link types without explicitly storing the linking values within the document itself as shown in the snipped below. + +==== +[source,java] +---- +@Document +class Book { + + @Id + ObjectId id; + String title; + List author; + + ObjectId publisherId; <1> +} + +@Document +class Publisher { + + @Id + ObjectId id; + String acronym; + String name; + + @ReadOnlyProperty <2> + @DocumentReference(lookup="{'publisherId':?#{#self._id} }") <3> + List books; +} +---- + +.`Book` document +[source,json] +---- +{ + "_id" : 9a48e32, + "title" : "The Warded Man", + "author" : ["Peter V. Brett"], + "publisherId" : 8cfb002 +} +---- + +.`Publisher` document +[source,json] +---- +{ + "_id" : 8cfb002, + "acronym" : "DR", + "name" : "Del Rey" +} +---- +<1> Set up the link from `Book` to `Publisher` by storing the `Publisher.id` within the `Book` document. +<2> Mark the property holding the references to be read only. This prevents storing references to individual ``Book``s with the `Publisher` document. +<3> Use the `#self` variable to access values within the `Publisher` document and in this retrieve `Books` with matching `publisherId`. +==== + With all the above in place it is possible to model all kind of associations between entities. Have a look at the non-exhaustive list of samples below to get feeling for what is possible. From 977e5e4c5c877e17a25de14bb47f98f8fa802161 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Sep 2021 13:50:54 +0200 Subject: [PATCH 0531/1381] Polishing. Tweak reference documentation wording. Extract self/target source dereferencing into utility methods. See: #3798 Original pull request: #3802. --- .../core/convert/DocumentReferenceSource.java | 25 +++++++++++++++++-- .../core/convert/ReferenceLookupDelegate.java | 17 +++---------- .../reference/document-references.adoc | 7 +++--- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java index 03e5eb0d5d..89d7360e4d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentReferenceSource.java @@ -28,11 +28,11 @@ public class DocumentReferenceSource { private final Object self; - @Nullable private final Object targetSource; + private final @Nullable Object targetSource; /** * Create a new instance of {@link DocumentReferenceSource}. - * + * * @param self the entire wrapper object holding references. Must not be {@literal null}. * @param targetSource the reference value source. */ @@ -60,4 +60,25 @@ public Object getSelf() { public Object getTargetSource() { return targetSource; } + + /** + * Dereference a {@code targetSource} if it is a {@link DocumentReferenceSource} or return {@code source} otherwise. + * + * @param source + * @return + */ + @Nullable + static Object getTargetSource(Object source) { + return source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getTargetSource() : source; + } + + /** + * Dereference a {@code self} object if it is a {@link DocumentReferenceSource} or return {@code self} otherwise. + * + * @param self + * @return + */ + static Object getSelf(Object self) { + return self instanceof DocumentReferenceSource ? ((DocumentReferenceSource) self).getSelf() : self; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index e16f9024b5..36ccc23a6b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -174,7 +174,6 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop * @param * @return can be {@literal null}. */ - @Nullable @SuppressWarnings("unchecked") private T parseValueOrGet(String value, ParameterBindingContext bindingContext, Supplier defaultValue) { @@ -199,16 +198,10 @@ private T parseValueOrGet(String value, ParameterBindingContext bindingConte ParameterBindingContext bindingContext(MongoPersistentProperty property, Object source, SpELContext spELContext) { - ValueProvider valueProvider; - if (source instanceof DocumentReferenceSource) { - valueProvider = valueProviderFor(((DocumentReferenceSource) source).getTargetSource()); - } else { - valueProvider = valueProviderFor(source); - } + ValueProvider valueProvider = valueProviderFor(DocumentReferenceSource.getTargetSource(source)); return new ParameterBindingContext(valueProvider, spELContext.getParser(), () -> evaluationContextFor(property, source, spELContext)); - } ValueProvider valueProviderFor(Object source) { @@ -232,8 +225,7 @@ EvaluationContext evaluationContextFor(MongoPersistentProperty property, Object EvaluationContext ctx = spELContext.getEvaluationContext(target); ctx.setVariable("target", target); - ctx.setVariable("self", - source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getSelf() : source); + ctx.setVariable("self", DocumentReferenceSource.getSelf(source)); ctx.setVariable(property.getName(), target); return ctx; @@ -255,11 +247,10 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so String lookup = documentReference.lookup(); - Object value = source instanceof DocumentReferenceSource ? ((DocumentReferenceSource) source).getTargetSource() - : source; + Object value = DocumentReferenceSource.getTargetSource(source); Document sort = parseValueOrGet(documentReference.sort(), bindingContext(property, source, spELContext), - () -> new Document()); + Document::new); if (property.isCollectionLike() && (value instanceof Collection || value == null)) { diff --git a/src/main/asciidoc/reference/document-references.adoc b/src/main/asciidoc/reference/document-references.adoc index 23bc025e80..b7d55678a5 100644 --- a/src/main/asciidoc/reference/document-references.adoc +++ b/src/main/asciidoc/reference/document-references.adoc @@ -263,7 +263,7 @@ class Publisher { ==== It is also possible to model relational style _One-To-Many_ references using a combination of `@ReadonlyProperty` and `@DocumentReference`. -This approach allows to link types without explicitly storing the linking values within the document itself as shown in the snipped below. +This approach allows link types without storing the linking values within the owning document but rather on the referencing document as shown in the example below. ==== [source,java] @@ -313,8 +313,9 @@ class Publisher { "name" : "Del Rey" } ---- -<1> Set up the link from `Book` to `Publisher` by storing the `Publisher.id` within the `Book` document. -<2> Mark the property holding the references to be read only. This prevents storing references to individual ``Book``s with the `Publisher` document. +<1> Set up the link from `Book` (reference) to `Publisher` (owner) by storing the `Publisher.id` within the `Book` document. +<2> Mark the property holding the references to be readonly. +This prevents storing references to individual ``Book``s with the `Publisher` document. <3> Use the `#self` variable to access values within the `Publisher` document and in this retrieve `Books` with matching `publisherId`. ==== From ada7e199a4dcbc2cea45d6c0e13d5a9cb8fde7b5 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Tue, 7 Sep 2021 14:54:12 +0200 Subject: [PATCH 0532/1381] Properly detect all supported identifier annotations as explicitly annotated. We now simply delegate to AnnotationBasedPersistentProperty.isIdProperty() for the detection of annotated identifiers. The previous, manual identifier check was preventing additional identifier annotations, supported by ABP, to be considered, too. Fixes #3803. --- spring-data-mongodb/pom.xml | 9 +++++++++ .../mapping/BasicMongoPersistentProperty.java | 3 +-- .../BasicMongoPersistentPropertyUnitTests.java | 15 ++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 1f157e75bc..2f73c10eba 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -317,6 +317,15 @@ test + + + + org.jmolecules + jmolecules-ddd + ${jmolecules} + test + + diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 87eb56b732..1315757896 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -22,7 +22,6 @@ import org.bson.types.ObjectId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.data.annotation.Id; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; @@ -115,7 +114,7 @@ public boolean isIdProperty() { */ @Override public boolean isExplicitIdProperty() { - return isAnnotationPresent(Id.class); + return super.isIdProperty(); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index bbcb8dada0..fffa861914 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -28,9 +28,9 @@ import org.bson.Document; import org.bson.types.ObjectId; +import org.jmolecules.ddd.annotation.Identity; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import org.springframework.core.annotation.AliasFor; import org.springframework.data.annotation.Id; import org.springframework.data.mapping.MappingException; @@ -241,6 +241,15 @@ void fieldTypeShouldBeDocumentForPropertiesAnnotatedIdWhenAComplexTypeAndFieldTy assertThat(property.getFieldType()).isEqualTo(Document.class); } + @Test + void considersJMoleculesIdentityExplicitlyAnnotatedIdentifier() { + + MongoPersistentProperty property = getPropertyFor(WithJMoleculesIdentity.class, "identifier"); + + assertThat(property.isIdProperty()).isTrue(); + assertThat(property.isExplicitIdProperty()).isTrue(); + } + private MongoPersistentProperty getPropertyFor(Field field) { return getPropertyFor(entity, field); } @@ -369,4 +378,8 @@ static class WithComplexId { @Id @org.springframework.data.mongodb.core.mapping.Field ComplexId id; } + + static class WithJMoleculesIdentity { + @Identity ObjectId identifier; + } } From cba7eaba4c442c426c3cba15be5d2c7073ebdb16 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Tue, 7 Sep 2021 14:54:35 +0200 Subject: [PATCH 0533/1381] Polishing. Formatting and indentation in parent project's pom.xml. See #3803 --- pom.xml | 8 ++++---- .../mapping/BasicMongoPersistentPropertyUnitTests.java | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 5d28c8a5c5..4aa47bbf2b 100644 --- a/pom.xml +++ b/pom.xml @@ -141,11 +141,11 @@ sonatype-libs-snapshot https://oss.sonatype.org/content/repositories/snapshots - false - + false + - true - + true + diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index fffa861914..66ae0199fc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -356,8 +356,7 @@ static class DocumentWithComposedAnnotations { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Id - static @interface ComposedIdAnnotation { - } + static @interface ComposedIdAnnotation {} static class WithStringMongoId { From 061c28f84ac8c8a302dffc6e3d7264d3703a0f6d Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Sep 2021 13:58:37 +0200 Subject: [PATCH 0534/1381] Polishing. Add ticket reference to tests. See #3803 --- .../core/mapping/BasicMongoPersistentPropertyUnitTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 66ae0199fc..d731854a02 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -241,7 +241,7 @@ void fieldTypeShouldBeDocumentForPropertiesAnnotatedIdWhenAComplexTypeAndFieldTy assertThat(property.getFieldType()).isEqualTo(Document.class); } - @Test + @Test // GH-3803 void considersJMoleculesIdentityExplicitlyAnnotatedIdentifier() { MongoPersistentProperty property = getPropertyFor(WithJMoleculesIdentity.class, "identifier"); From 4e960a968288833f6e8ca6a8ce429eef226972a4 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Sep 2021 09:24:15 +0200 Subject: [PATCH 0535/1381] Fix document reference on empty reference arrays. This commit fixes an issue caused by empty reference arrays. Closes #3805 Original pull request: #3807. --- .../core/convert/ReferenceLookupDelegate.java | 9 ++++- .../MongoTemplateDocumentReferenceTests.java | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index 36ccc23a6b..a2726e6338 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -122,7 +123,9 @@ private ReferenceCollection computeReferenceContext(MongoPersistentProperty prop // Use the first value as a reference for others in case of collection like if (value instanceof Iterable) { - value = ((Iterable) value).iterator().next(); + + Iterator iterator = ((Iterable) value).iterator(); + value = iterator.hasNext() ? iterator.next() : new Document(); } // handle DBRef value @@ -266,6 +269,10 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so ors.add(decoded); } + if(ors.isEmpty()) { + return new ListDocumentReferenceQuery(new Document("_id", new Document("$exists", false)), sort); + } + return new ListDocumentReferenceQuery(new Document("$or", ors), sort); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index 06d288d1f5..2b96b3dc22 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -25,6 +25,7 @@ import lombok.Setter; import lombok.ToString; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; @@ -679,6 +680,41 @@ void loadCollectionReferenceWithMissingRefs() { assertThat(result.getSimpleValueRef()).containsExactly(new SimpleObjectRef("ref-2", "me-the-2-referenced-object")); } + @Test // GH-3805 + void loadEmptyCollectionReference() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + // an empty reference array. + Document source = new Document("_id", "id-1").append("value", "v1").append("simplePreinitializedValueRef", + Collections.emptyList()); + + template.execute(db -> { + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.simplePreinitializedValueRef).isEmpty(); + } + + @Test // GH-3805 + void loadNoExistingCollectionReference() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + // no reference array at all + Document source = new Document("_id", "id-1").append("value", "v1"); + + template.execute(db -> { + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.simplePreinitializedValueRef).isEmpty(); + } + @Test // GH-3602 void queryForReference() { @@ -1122,6 +1158,9 @@ static class CollectionRefRoot { @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") // List simpleValueRef; + @DocumentReference + List simplePreinitializedValueRef = new ArrayList<>(); + @DocumentReference(lookup = "{ '_id' : '?#{#target}' }", sort = "{ '_id' : -1 } ") // List simpleSortedValueRef; From 270456ed81ae3a11d08ec6a3a3bffd8eca9b8d77 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Sep 2021 14:18:17 +0200 Subject: [PATCH 0536/1381] Polishing. Extract query that yields no hits into constant. Guard Map-typed reference properties against empty $or. See #3805 Original pull request: #3807. --- .../core/convert/ReferenceLookupDelegate.java | 25 +++++++++++++------ .../MongoTemplateDocumentReferenceTests.java | 21 ++++++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index a2726e6338..dbbdbe99eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -62,6 +62,8 @@ */ public final class ReferenceLookupDelegate { + private static final Document NO_RESULTS_PREDICATE = new Document("_id", new Document("$exists", false)); + private final MappingContext, MongoPersistentProperty> mappingContext; private final SpELContext spELContext; private final ParameterBindingDocumentCodec codec; @@ -262,15 +264,17 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so sort); } - List ors = new ArrayList<>(); - for (Object entry : (Collection) value) { + Collection objects = (Collection) value; - Document decoded = codec.decode(lookup, bindingContext(property, entry, spELContext)); - ors.add(decoded); + if (objects.isEmpty()) { + return new ListDocumentReferenceQuery(NO_RESULTS_PREDICATE, sort); } - if(ors.isEmpty()) { - return new ListDocumentReferenceQuery(new Document("_id", new Document("$exists", false)), sort); + List ors = new ArrayList<>(objects.size()); + for (Object entry : objects) { + + Document decoded = codec.decode(lookup, bindingContext(property, entry, spELContext)); + ors.add(decoded); } return new ListDocumentReferenceQuery(new Document("$or", ors), sort); @@ -278,9 +282,14 @@ DocumentReferenceQuery computeFilter(MongoPersistentProperty property, Object so if (property.isMap() && value instanceof Map) { - Map filterMap = new LinkedHashMap<>(); + Set> entries = ((Map) value).entrySet(); + if (entries.isEmpty()) { + return new MapDocumentReferenceQuery(NO_RESULTS_PREDICATE, sort, Collections.emptyMap()); + } + + Map filterMap = new LinkedHashMap<>(entries.size()); - for (Entry entry : ((Map) value).entrySet()) { + for (Entry entry : entries) { Document decoded = codec.decode(lookup, bindingContext(property, entry.getValue(), spELContext)); filterMap.put(entry.getKey(), decoded); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index 2b96b3dc22..c63e7a1115 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -698,6 +698,24 @@ void loadEmptyCollectionReference() { assertThat(result.simplePreinitializedValueRef).isEmpty(); } + @Test // GH-3805 + void loadEmptyMapReference() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + // an empty reference array. + Document source = new Document("_id", "id-1").append("value", "v1").append("simplePreinitializedMapRef", + new Document()); + + template.execute(db -> { + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.simplePreinitializedMapRef).isEmpty(); + } + @Test // GH-3805 void loadNoExistingCollectionReference() { @@ -1167,6 +1185,9 @@ static class CollectionRefRoot { @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") // Map mapValueRef; + @DocumentReference // + Map simplePreinitializedMapRef = new LinkedHashMap<>(); + @Field("simple-value-ref-annotated-field-name") // @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") // List simpleValueRefWithAnnotatedFieldName; From f128e6df152bc559bbae6e07592307d3f3fc402d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Sep 2021 10:29:02 +0200 Subject: [PATCH 0537/1381] Fix `@DocumentReference` resolution for properties used in constructor. This commit fixes an issue that prevented referenced entities from being used as constructor arguments. Closes: #3806 Original pull request: #3810. --- .../core/convert/MappingMongoConverter.java | 25 +++-- .../MongoTemplateDocumentReferenceTests.java | 106 ++++++++++++++++++ 2 files changed, 124 insertions(+), 7 deletions(-) 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 5a2c3e952a..07709df365 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 @@ -530,7 +530,7 @@ private void readAssociation(Association association, P if (conversionService.canConvert(DocumentPointer.class, property.getActualType())) { - if(value == null) { + if (value == null) { return; } @@ -541,7 +541,9 @@ private void readAssociation(Association association, P } else { accessor.setProperty(property, - dbRefResolver.resolveReference(property, new DocumentReferenceSource(documentAccessor.getDocument(), documentAccessor.get(property)), referenceLookupDelegate, context::convert)); + dbRefResolver.resolveReference(property, + new DocumentReferenceSource(documentAccessor.getDocument(), documentAccessor.get(property)), + referenceLookupDelegate, context::convert)); } return; } @@ -875,10 +877,12 @@ protected List createCollection(Collection collection, MongoPersisten if (property.isAssociation()) { List targetCollection = collection.stream().map(it -> { - return documentPointerFactory.computePointer(mappingContext, property, it, property.getActualType()).getPointer(); + return documentPointerFactory.computePointer(mappingContext, property, it, property.getActualType()) + .getPointer(); }).collect(Collectors.toList()); - return writeCollectionInternal(targetCollection, ClassTypeInformation.from(DocumentPointer.class), new ArrayList<>()); + return writeCollectionInternal(targetCollection, ClassTypeInformation.from(DocumentPointer.class), + new ArrayList<>()); } if (property.hasExplicitWriteTarget()) { @@ -931,7 +935,8 @@ protected Bson createMap(Map map, MongoPersistentProperty proper if (property.isDbReference()) { document.put(simpleKey, value != null ? createDBRef(value, property) : null); } else { - document.put(simpleKey, documentPointerFactory.computePointer(mappingContext, property, value, property.getActualType()).getPointer()); + document.put(simpleKey, documentPointerFactory + .computePointer(mappingContext, property, value, property.getActualType()).getPointer()); } } else { @@ -1814,6 +1819,11 @@ public T getPropertyValue(MongoPersistentProperty property) { return (T) dbRefResolver.resolveDbRef(property, dbref, callback, dbRefProxyHandler); } + if (property.isDocumentReference()) { + return (T) dbRefResolver.resolveReference(property, accessor.get(property), referenceLookupDelegate, + context::convert); + } + return super.getPropertyValue(property); } } @@ -2036,7 +2046,7 @@ public S convert(Object source, TypeInformation if (typeHint.isMap()) { - if(ClassUtils.isAssignable(Document.class, typeHint.getType())) { + if (ClassUtils.isAssignable(Document.class, typeHint.getType())) { return (S) documentConverter.convert(this, BsonUtils.asBson(source), typeHint); } @@ -2044,7 +2054,8 @@ public S convert(Object source, TypeInformation return (S) mapConverter.convert(this, BsonUtils.asBson(source), typeHint); } - throw new IllegalArgumentException(String.format("Expected map like structure but found %s", source.getClass())); + throw new IllegalArgumentException( + String.format("Expected map like structure but found %s", source.getClass())); } if (source instanceof DBRef) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index c63e7a1115..3abd3a3add 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -733,6 +733,52 @@ void loadNoExistingCollectionReference() { assertThat(result.simplePreinitializedValueRef).isEmpty(); } + @Test // GH-3806 + void resolveReferenceWhenUsedAsCtorArgument() { + + Publisher publisher = new Publisher(); + publisher.id = "p-111"; + publisher.name = "ppp"; + + template.save(publisher); + + WithRequiredArgsCtor source = new WithRequiredArgsCtor("id-1", publisher); + + template.save(source); + + WithRequiredArgsCtor target = template.findOne(query(where("id").is(source.id)), WithRequiredArgsCtor.class); + assertThat(target.publisher).isNotNull(); + } + + @Test // GH-3806 + void resolveLazyReferenceWhenUsedAsCtorArgument() { + + Publisher publisher = new Publisher(); + publisher.id = "p-111"; + publisher.name = "ppp"; + + template.save(publisher); + + WithLazyRequiredArgsCtor source = new WithLazyRequiredArgsCtor("id-1", publisher); + + template.save(source); + + WithLazyRequiredArgsCtor target = template.findOne(query(where("id").is(source.id)), WithLazyRequiredArgsCtor.class); + + // proxy not yet resolved + LazyLoadingTestUtils.assertProxy(target.publisher, (proxy) -> { + + assertThat(proxy.isResolved()).isFalse(); + assertThat(proxy.currentValue()).isNull(); + }); + + // resolve the proxy by invoking a method on it + assertThat(target.getPublisher().getName()).isEqualTo("ppp"); + LazyLoadingTestUtils.assertProxy(target.publisher, (proxy) -> { + assertThat(proxy.isResolved()).isTrue(); + }); + } + @Test // GH-3602 void queryForReference() { @@ -1371,6 +1417,30 @@ static class Publisher { String id; String acronym; String name; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAcronym() { + return acronym; + } + + public void setAcronym(String acronym) { + this.acronym = acronym; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } @Data @@ -1401,4 +1471,40 @@ static class OneToManyStylePublisher { @DocumentReference(lookup="{'publisherId':?#{#self._id} }") List books; } + + static class WithRequiredArgsCtor { + + final String id; + + @DocumentReference + final Publisher publisher; + + public WithRequiredArgsCtor(String id, Publisher publisher) { + + this.id = id; + this.publisher = publisher; + } + } + + static class WithLazyRequiredArgsCtor { + + final String id; + + @DocumentReference(lazy = true) + final Publisher publisher; + + public WithLazyRequiredArgsCtor(String id, Publisher publisher) { + + this.id = id; + this.publisher = publisher; + } + + public String getId() { + return id; + } + + public Publisher getPublisher() { + return publisher; + } + } } From 9014f770d8027c4e1bb35fa91b80d16ac4f6e09e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Sep 2021 13:33:46 +0200 Subject: [PATCH 0538/1381] Fix slice argument in query fields projection. We now use a Collection instead of an Array to pass on $slice projection values for offset and limit. Closes: #3811 Original pull request: #3812. --- .../data/mongodb/core/query/Field.java | 3 ++- .../data/mongodb/core/MongoTemplateTests.java | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java index 0561bbdca6..02450505b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Field.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.query; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -192,7 +193,7 @@ public Field slice(String field, int size) { */ public Field slice(String field, int offset, int size) { - slices.put(field, new Integer[] { offset, size }); + slices.put(field, Arrays.asList(offset, size)); return this; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 28cdaa4830..33ae0ef994 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -3768,6 +3768,23 @@ void shouldFindSubdocumentWithNullCorrectly() { assertThat(loaded).isNotNull(); } + @Test // GH-3811 + public void sliceShouldLimitCollectionValues() { + + DocumentWithCollectionOfSimpleType source = new DocumentWithCollectionOfSimpleType(); + source.id = "id-1"; + source.values = Arrays.asList("spring", "data", "mongodb"); + + template.save(source); + + Criteria criteria = Criteria.where("id").is(source.id); + Query query = Query.query(criteria); + query.fields().slice("values", 0, 1); + DocumentWithCollectionOfSimpleType target = template.findOne(query, DocumentWithCollectionOfSimpleType.class); + + assertThat(target.values).containsExactly("spring"); + } + private AtomicReference createAfterSaveReference() { AtomicReference saved = new AtomicReference<>(); From 8fb0e1326b3a33591fca6c7a6ace8fb2088a91ec Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Sep 2021 10:03:45 +0200 Subject: [PATCH 0539/1381] Introduce `SessionSynchronization.NEVER` to disable transactional participation. SessionSynchronization.NEVER bypasses all transactional integration in cases where applications do not want to make use of transactions so that transaction inspection overhead is avoided. Closes: #3760 Original Pull Request: #3809 --- .../data/mongodb/MongoDatabaseUtils.java | 3 ++- .../mongodb/ReactiveMongoDatabaseUtils.java | 4 ++++ .../data/mongodb/SessionSynchronization.java | 20 +++++++++++++--- .../mongodb/MongoDatabaseUtilsUnitTests.java | 24 +++++++++++++++++++ .../ReactiveMongoDatabaseUtilsUnitTests.java | 14 +++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index ba8efa536c..c9342ec4f6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -104,7 +104,8 @@ private static MongoDatabase doGetMongoDatabase(@Nullable String dbName, MongoDa Assert.notNull(factory, "Factory must not be null!"); - if (!TransactionSynchronizationManager.isSynchronizationActive()) { + if (sessionSynchronization == SessionSynchronization.NEVER + || !TransactionSynchronizationManager.isSynchronizationActive()) { return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java index 711947a30d..4699ac56c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java @@ -138,6 +138,10 @@ private static Mono doGetMongoDatabase(@Nullable String dbName, R Assert.notNull(factory, "DatabaseFactory must not be null!"); + if (sessionSynchronization == SessionSynchronization.NEVER) { + return getMongoDatabaseOrDefault(dbName, factory); + } + return TransactionSynchronizationManager.forCurrentTransaction() .filter(TransactionSynchronizationManager::isSynchronizationActive) // .flatMap(synchronizationManager -> { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java index 2223b82391..144d3d3cb3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionSynchronization.java @@ -15,13 +15,20 @@ */ package org.springframework.data.mongodb; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; + /** - * {@link SessionSynchronization} is used along with {@link org.springframework.data.mongodb.core.MongoTemplate} to - * define in which type of transactions to participate if any. + * {@link SessionSynchronization} is used along with {@code MongoTemplate} to define in which type of transactions to + * participate if any. * * @author Christoph Strobl * @author Mark Paluch * @since 2.1 + * @see MongoTemplate#setSessionSynchronization(SessionSynchronization) + * @see MongoDatabaseUtils#getDatabase(MongoDatabaseFactory, SessionSynchronization) + * @see ReactiveMongoTemplate#setSessionSynchronization(SessionSynchronization) + * @see ReactiveMongoDatabaseUtils#getDatabase(ReactiveMongoDatabaseFactory, SessionSynchronization) */ public enum SessionSynchronization { @@ -34,5 +41,12 @@ public enum SessionSynchronization { /** * Synchronize with native MongoDB transactions initiated via {@link MongoTransactionManager}. */ - ON_ACTUAL_TRANSACTION; + ON_ACTUAL_TRANSACTION, + + /** + * Do not participate in ongoing transactions. + * + * @since 3.2.5 + */ + NEVER; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java index 8cb222f0e6..5b0cd81cc2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java @@ -109,6 +109,30 @@ void shouldNotStartSessionWhenNoTransactionOngoing() { verify(dbFactory, never()).withSession(any(ClientSession.class)); } + @Test // GH-3760 + void shouldJustReturnDatabaseIfSessionSynchronizationDisabled() throws Exception { + + when(dbFactory.getMongoDatabase()).thenReturn(db); + + JtaTransactionManager txManager = new JtaTransactionManager(userTransaction); + TransactionTemplate txTemplate = new TransactionTemplate(txManager); + + txTemplate.execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { + + MongoDatabaseUtils.getDatabase(dbFactory, SessionSynchronization.NEVER); + + assertThat(TransactionSynchronizationManager.hasResource(dbFactory)).isFalse(); + } + }); + + verify(userTransaction).getStatus(); + verifyNoMoreInteractions(userTransaction); + verifyNoInteractions(session); + } + @Test // DATAMONGO-1920 void shouldParticipateInOngoingJtaTransactionWithCommitWhenSessionSychronizationIsAny() throws Exception { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java index 60a7ff9a47..a7393a1392 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtilsUnitTests.java @@ -88,6 +88,20 @@ void isTransactionActiveShouldLookupTxForActiveTransactionSynchronizationViaTxMa }).as(StepVerifier::create).expectNext(true).verifyComplete(); } + @Test // GH-3760 + void shouldJustReturnDatabaseIfSessionSynchronizationDisabled() { + + when(databaseFactory.getMongoDatabase()).thenReturn(Mono.just(db)); + + ReactiveMongoDatabaseUtils.getDatabase(databaseFactory, SessionSynchronization.NEVER) // + .as(StepVerifier::create) // + .expectNextCount(1) // + .verifyComplete(); + + verify(databaseFactory, never()).getSession(any()); + verify(databaseFactory, never()).withSession(any(ClientSession.class)); + } + @Test // DATAMONGO-2265 void shouldNotStartSessionWhenNoTransactionOngoing() { From a26e78095745ece93ed6711e62f44c1a80ac8a46 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 8 Sep 2021 10:04:58 +0200 Subject: [PATCH 0540/1381] Reduce allocations in query and update mapping. Introduce EmptyDocument and utility methods in BsonUtils. Avoid entrySet and iterator creation for document iterations/inspections. Relates to: #3760 Original Pull Request: #3809 --- .../data/mongodb/core/MappedDocument.java | 9 ++ .../data/mongodb/core/QueryOperations.java | 2 +- .../core/convert/DocumentAccessor.java | 2 +- .../core/convert/MappingMongoConverter.java | 14 +-- .../mongodb/core/convert/MongoConverter.java | 3 + .../mongodb/core/convert/QueryMapper.java | 53 +++++++---- .../data/mongodb/core/query/Meta.java | 18 +++- .../data/mongodb/core/query/Query.java | 33 +++++-- .../data/mongodb/core/query/TextQuery.java | 13 +-- .../data/mongodb/core/query/Update.java | 30 +++++- .../data/mongodb/util/BsonUtils.java | 63 ++++++++++++ .../data/mongodb/util/EmptyDocument.java | 95 +++++++++++++++++++ .../mongodb/core/MongoTemplateUnitTests.java | 7 +- .../data/mongodb/core/query/QueryTests.java | 16 ++-- .../query/PartTreeMongoQueryUnitTests.java | 7 +- 15 files changed, 298 insertions(+), 67 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/EmptyDocument.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java index 340c11bb99..e3c1f3d64c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappedDocument.java @@ -156,5 +156,14 @@ public Boolean isIsolated() { public List getArrayFilters() { return delegate.getArrayFilters(); } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.query.UpdateDefinition#hasArrayFilters() + */ + @Override + public boolean hasArrayFilters() { + return delegate.hasArrayFilters(); + } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java index 1ec8fc9366..e9431aa3d2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java @@ -613,7 +613,7 @@ class UpdateContext extends QueryContext { UpdateContext(MappedDocument update, boolean upsert) { - super(new BasicQuery(new Document(BsonUtils.asMap(update.getIdFilter())))); + super(new BasicQuery(BsonUtils.asDocument(update.getIdFilter()))); this.multi = false; this.upsert = upsert; this.mappedDocument = update; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java index 9c94487a3e..0b31f75341 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentAccessor.java @@ -135,7 +135,7 @@ public Object get(MongoPersistentProperty property) { */ @Nullable public Object getRawId(MongoPersistentEntity entity) { - return entity.hasIdProperty() ? get(entity.getRequiredIdProperty()) : BsonUtils.asMap(document).get("_id"); + return entity.hasIdProperty() ? get(entity.getRequiredIdProperty()) : BsonUtils.get(document, "_id"); } /** 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 07709df365..302c3dad45 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 @@ -25,7 +25,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -1325,21 +1324,22 @@ protected Map readMap(ConversionContext context, Bson bson, Type return map; } - for (Entry entry : sourceMap.entrySet()) { + sourceMap.forEach((k, v) -> { - if (typeMapper.isTypeKey(entry.getKey())) { - continue; + if (typeMapper.isTypeKey(k)) { + return; } - Object key = potentiallyUnescapeMapKey(entry.getKey()); + Object key = potentiallyUnescapeMapKey(k); if (!rawKeyType.isAssignableFrom(key.getClass())) { key = doConvert(key, rawKeyType); } - Object value = entry.getValue(); + Object value = v; map.put(key, value == null ? value : context.convert(value, valueType)); - } + + }); return map; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java index 20499d3173..aff1b8d8e0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverter.java @@ -140,6 +140,9 @@ default Object convertId(@Nullable Object id, Class targetType) { if (ObjectId.isValid(id.toString())) { return new ObjectId(id.toString()); } + + // avoid ConversionException as convertToMongoType will return String anyways. + return id; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index e7deb38231..356dd89faa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -193,12 +193,11 @@ public Document getMappedSort(Document sortObject, @Nullable MongoPersistentEnti Assert.notNull(sortObject, "SortObject must not be null!"); if (sortObject.isEmpty()) { - return new Document(); + return BsonUtils.EMPTY_DOCUMENT; } Document mappedSort = mapFieldsToPropertyNames(sortObject, entity); - mapMetaAttributes(mappedSort, entity, MetaMapping.WHEN_PRESENT); - return mappedSort; + return mapMetaAttributes(mappedSort, entity, MetaMapping.WHEN_PRESENT); } /** @@ -215,42 +214,51 @@ public Document getMappedFields(Document fieldsObject, @Nullable MongoPersistent Assert.notNull(fieldsObject, "FieldsObject must not be null!"); Document mappedFields = mapFieldsToPropertyNames(fieldsObject, entity); - mapMetaAttributes(mappedFields, entity, MetaMapping.FORCE); - return mappedFields; + return mapMetaAttributes(mappedFields, entity, MetaMapping.FORCE); } private Document mapFieldsToPropertyNames(Document fields, @Nullable MongoPersistentEntity entity) { if (fields.isEmpty()) { - return new Document(); + return BsonUtils.EMPTY_DOCUMENT; } Document target = new Document(); - for (Map.Entry entry : BsonUtils.asMap(filterUnwrappedObjects(fields, entity)).entrySet()) { - Field field = createPropertyField(entity, entry.getKey(), mappingContext); + BsonUtils.asMap(filterUnwrappedObjects(fields, entity)).forEach((k, v) -> { + + Field field = createPropertyField(entity, k, mappingContext); if (field.getProperty() != null && field.getProperty().isUnwrapped()) { - continue; + return; } - target.put(field.getMappedKey(), entry.getValue()); - } + target.put(field.getMappedKey(), v); + }); + return target; } - private void mapMetaAttributes(Document source, @Nullable MongoPersistentEntity entity, MetaMapping metaMapping) { + private Document mapMetaAttributes(Document source, @Nullable MongoPersistentEntity entity, + MetaMapping metaMapping) { if (entity == null) { - return; + return source; } if (entity.hasTextScoreProperty() && !MetaMapping.IGNORE.equals(metaMapping)) { + + if (source == BsonUtils.EMPTY_DOCUMENT) { + source = new Document(); + } + MongoPersistentProperty textScoreProperty = entity.getTextScoreProperty(); if (MetaMapping.FORCE.equals(metaMapping) || (MetaMapping.WHEN_PRESENT.equals(metaMapping) && source.containsKey(textScoreProperty.getFieldName()))) { source.putAll(getMappedTextScoreField(textScoreProperty)); } } + + return source; } private Document filterUnwrappedObjects(Document fieldsObject, @Nullable MongoPersistentEntity entity) { @@ -679,7 +687,7 @@ protected final Entry createMapEntry(Field field, @Nullable Obje private Entry createMapEntry(String key, @Nullable Object value) { Assert.hasText(key, "Key must not be null or empty!"); - return Collections.singletonMap(key, value).entrySet().iterator().next(); + return new AbstractMap.SimpleEntry<>(key, value); } private Object createReferenceFor(Object source, MongoPersistentProperty property) { @@ -733,13 +741,13 @@ protected boolean isNestedKeyword(@Nullable Object candidate) { return false; } - Set keys = BsonUtils.asMap((Bson) candidate).keySet(); + Map map = BsonUtils.asMap((Bson) candidate); - if (keys.size() != 1) { + if (map.size() != 1) { return false; } - return isKeyword(keys.iterator().next()); + return isKeyword(map.entrySet().iterator().next().getKey()); } /** @@ -823,11 +831,14 @@ public Keyword(Bson source, String key) { public Keyword(Bson bson) { - Set keys = BsonUtils.asMap(bson).keySet(); - Assert.isTrue(keys.size() == 1, "Can only use a single value Document!"); + Map map = BsonUtils.asMap(bson); + Assert.isTrue(map.size() == 1, "Can only use a single value Document!"); + + Set> entries = map.entrySet(); + Entry entry = entries.iterator().next(); - this.key = keys.iterator().next(); - this.value = BsonUtils.get(bson, key); + this.key = entry.getKey(); + this.value = entry.getValue(); } /** 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 2bfddfa2cd..d70a21707f 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 @@ -49,8 +49,8 @@ private enum MetaKey { } } - private final Map values = new LinkedHashMap<>(2); - private final Set flags = new LinkedHashSet<>(); + private Map values = Collections.emptyMap(); + private Set flags = Collections.emptySet(); private Integer cursorBatchSize; private Boolean allowDiskUse; @@ -63,8 +63,9 @@ public Meta() {} * @param source */ Meta(Meta source) { - this.values.putAll(source.values); - this.flags.addAll(source.flags); + + this.values = new LinkedHashMap<>(source.values); + this.flags = new LinkedHashSet<>(source.flags); this.cursorBatchSize = source.cursorBatchSize; this.allowDiskUse = source.allowDiskUse; } @@ -158,6 +159,11 @@ public void setCursorBatchSize(int cursorBatchSize) { public boolean addFlag(CursorOption option) { Assert.notNull(option, "CursorOption must not be null!"); + + if (this.flags == Collections.EMPTY_SET) { + this.flags = new LinkedHashSet<>(2); + } + return this.flags.add(option); } @@ -220,6 +226,10 @@ void setValue(String key, @Nullable Object value) { Assert.hasText(key, "Meta key must not be 'null' or blank."); + if (values == Collections.EMPTY_MAP) { + values = new LinkedHashMap<>(2); + } + if (value == null || (value instanceof String && !StringUtils.hasText((String) value))) { this.values.remove(key); } 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 1f54e7049d..ce60798bf5 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 @@ -21,6 +21,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -30,6 +31,7 @@ import java.util.concurrent.TimeUnit; import org.bson.Document; + import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Order; @@ -52,7 +54,7 @@ public class Query { private static final String RESTRICTED_TYPES_KEY = "_$RESTRICTED_TYPES"; - private final Set> restrictedTypes = new HashSet<>(); + private Set> restrictedTypes = Collections.emptySet(); private final Map criteria = new LinkedHashMap<>(); private @Nullable Field fieldSpec = null; private Sort sort = Sort.unsorted(); @@ -235,8 +237,15 @@ public Query restrict(Class type, Class... additionalTypes) { Assert.notNull(type, "Type must not be null!"); Assert.notNull(additionalTypes, "AdditionalTypes must not be null"); + if (restrictedTypes == Collections.EMPTY_SET) { + restrictedTypes = new HashSet<>(1 + additionalTypes.length); + } + restrictedTypes.add(type); - restrictedTypes.addAll(Arrays.asList(additionalTypes)); + + if (additionalTypes.length > 0) { + restrictedTypes.addAll(Arrays.asList(additionalTypes)); + } return this; } @@ -246,6 +255,17 @@ public Query restrict(Class type, Class... additionalTypes) { */ public Document getQueryObject() { + if (criteria.isEmpty() && restrictedTypes.isEmpty()) { + return BsonUtils.EMPTY_DOCUMENT; + } + + if (criteria.size() == 1 && restrictedTypes.isEmpty()) { + + for (CriteriaDefinition definition : criteria.values()) { + return definition.getCriteriaObject(); + } + } + Document document = new Document(); for (CriteriaDefinition definition : criteria.values()) { @@ -263,7 +283,7 @@ public Document getQueryObject() { * @return the field {@link Document}. */ public Document getFieldsObject() { - return this.fieldSpec == null ? new Document() : fieldSpec.getFieldsObject(); + return this.fieldSpec == null ? BsonUtils.EMPTY_DOCUMENT : fieldSpec.getFieldsObject(); } /** @@ -272,13 +292,12 @@ public Document getFieldsObject() { public Document getSortObject() { if (this.sort.isUnsorted()) { - return new Document(); + return BsonUtils.EMPTY_DOCUMENT; } Document document = new Document(); - this.sort.stream()// - .forEach(order -> document.put(order.getProperty(), order.isAscending() ? 1 : -1)); + this.sort.forEach(order -> document.put(order.getProperty(), order.isAscending() ? 1 : -1)); return document; } @@ -557,7 +576,7 @@ public boolean isSorted() { target.limit = source.getLimit(); target.hint = source.getHint(); target.collation = source.getCollation(); - target.restrictedTypes.addAll(source.getRestrictedTypes()); + target.restrictedTypes = new HashSet<>(source.getRestrictedTypes()); if (source.getMeta().hasValues()) { target.setMeta(new Meta(source.getMeta())); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java index 9a72b3ffc0..84a5b9d47e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java @@ -18,6 +18,8 @@ import java.util.Locale; import org.bson.Document; + +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; /** @@ -157,7 +159,7 @@ public Document getFieldsObject() { return super.getFieldsObject(); } - Document fields = super.getFieldsObject(); + Document fields = BsonUtils.asMutableDocument(super.getFieldsObject()); fields.put(getScoreFieldName(), META_TEXT_SCORE); return fields; @@ -170,15 +172,14 @@ public Document getFieldsObject() { @Override public Document getSortObject() { - Document sort = new Document(); - if (this.sortByScore) { + Document sort = new Document(); sort.put(getScoreFieldName(), META_TEXT_SCORE); + sort.putAll(super.getSortObject()); + return sort; } - sort.putAll(super.getSortObject()); - - return sort; + return super.getSortObject(); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index 34cab18c31..bdea768d31 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -56,10 +56,10 @@ public enum Position { } private boolean isolated = false; - private Set keysToUpdate = new HashSet<>(); - private Map modifierOps = new LinkedHashMap<>(); - private Map pushCommandBuilders = new LinkedHashMap<>(1); - private List arrayFilters = new ArrayList<>(); + private final Set keysToUpdate = new HashSet<>(); + private final Map modifierOps = new LinkedHashMap<>(); + private Map pushCommandBuilders = Collections.emptyMap(); + private List arrayFilters = Collections.emptyList(); /** * Static factory method to create an Update using the provided key @@ -193,6 +193,11 @@ public Update push(String key, @Nullable Object value) { public PushOperatorBuilder push(String key) { if (!pushCommandBuilders.containsKey(key)) { + + if (pushCommandBuilders == Collections.EMPTY_MAP) { + pushCommandBuilders = new LinkedHashMap<>(1); + } + pushCommandBuilders.put(key, new PushOperatorBuilder(key)); } return pushCommandBuilders.get(key); @@ -412,6 +417,10 @@ public Update isolated() { */ public Update filterArray(CriteriaDefinition criteria) { + if (arrayFilters == Collections.EMPTY_LIST) { + this.arrayFilters = new ArrayList<>(); + } + this.arrayFilters.add(criteria::getCriteriaObject); return this; } @@ -427,6 +436,10 @@ public Update filterArray(CriteriaDefinition criteria) { */ public Update filterArray(String identifier, Object expression) { + if (arrayFilters == Collections.EMPTY_LIST) { + this.arrayFilters = new ArrayList<>(); + } + this.arrayFilters.add(() -> new Document(identifier, expression)); return this; } @@ -455,6 +468,15 @@ public List getArrayFilters() { return Collections.unmodifiableList(this.arrayFilters); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.query.UpdateDefinition#hasArrayFilters() + */ + @Override + public boolean hasArrayFilters() { + return !this.arrayFilters.isEmpty(); + } + /** * This method is not called anymore rather override {@link #addMultiFieldOperation(String, String, Object)}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java index d452ad662f..c540a14603 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java @@ -60,12 +60,26 @@ */ public class BsonUtils { + /** + * The empty document (immutable). This document is serializable. + * + * @since 3.2.5 + */ + public static final Document EMPTY_DOCUMENT = new EmptyDocument(); + @SuppressWarnings("unchecked") @Nullable public static T get(Bson bson, String key) { return (T) asMap(bson).get(key); } + /** + * Return the {@link Bson} object as {@link Map}. Depending on the input type, the return value can be either a casted + * version of {@code bson} or a converted (detached from the original value). + * + * @param bson + * @return + */ public static Map asMap(Bson bson) { if (bson instanceof Document) { @@ -81,6 +95,55 @@ public static Map asMap(Bson bson) { return (Map) bson.toBsonDocument(Document.class, MongoClientSettings.getDefaultCodecRegistry()); } + /** + * Return the {@link Bson} object as {@link Document}. Depending on the input type, the return value can be either a + * casted version of {@code bson} or a converted (detached from the original value). + * + * @param bson + * @return + * @since 3.2.5 + */ + public static Document asDocument(Bson bson) { + + if (bson instanceof Document) { + return (Document) bson; + } + + Map map = asMap(bson); + + if (map instanceof Document) { + return (Document) map; + } + + return new Document(map); + } + + /** + * Return the {@link Bson} object as mutable {@link Document} containing all entries from {@link Bson}. + * + * @param bson + * @return a mutable {@link Document} containing all entries from {@link Bson}. + * @since 3.2.5 + */ + public static Document asMutableDocument(Bson bson) { + + if (bson instanceof EmptyDocument) { + bson = new Document(asDocument(bson)); + } + + if (bson instanceof Document) { + return (Document) bson; + } + + Map map = asMap(bson); + + if (map instanceof Document) { + return (Document) map; + } + + return new Document(map); + } + public static void addToMap(Bson bson, String key, @Nullable Object value) { if (bson instanceof Document) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/EmptyDocument.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/EmptyDocument.java new file mode 100644 index 0000000000..83c95c82e5 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/EmptyDocument.java @@ -0,0 +1,95 @@ +/* + * Copyright 2021 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 + * + * https://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.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.function.BiFunction; + +import org.bson.Document; +import org.jetbrains.annotations.Nullable; + +/** + * Empty variant of {@link Document}. + * + * @author Mark Paluch + */ +class EmptyDocument extends Document { + + @Override + public Document append(String key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Object put(String key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + @Override + public void replaceAll(BiFunction function) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean replace(String key, Object oldValue, Object newValue) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public Object replace(String key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Set> entrySet() { + return Collections.emptySet(); + } + + @Override + public Collection values() { + return Collections.emptyList(); + } + + @Override + public Set keySet() { + return Collections.emptySet(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 147d2e49c3..b1d3d6a839 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -101,6 +101,7 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.timeseries.Granularity; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; @@ -1071,7 +1072,7 @@ void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonSpELProjection.class, CursorPreparer.NO_OP_PREPARER); - verify(findIterable).projection(eq(new Document())); + verify(findIterable).projection(eq(BsonUtils.EMPTY_DOCUMENT)); } @Test // DATAMONGO-1733, DATAMONGO-2041 @@ -1098,7 +1099,7 @@ void doesNotApplyFieldsWhenTargetIsNotAProjection() { template.doFind("star-wars", new Document(), new Document(), Person.class, Person.class, CursorPreparer.NO_OP_PREPARER); - verify(findIterable).projection(eq(new Document())); + verify(findIterable).projection(eq(BsonUtils.EMPTY_DOCUMENT)); } @Test // DATAMONGO-1733 @@ -1107,7 +1108,7 @@ void doesNotApplyFieldsWhenTargetExtendsDomainType() { template.doFind("star-wars", new Document(), new Document(), Person.class, PersonExtended.class, CursorPreparer.NO_OP_PREPARER); - verify(findIterable).projection(eq(new Document())); + verify(findIterable).projection(eq(BsonUtils.EMPTY_DOCUMENT)); } @Test // DATAMONGO-1348, DATAMONGO-2264 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java index 01dddcd084..69da412073 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryTests.java @@ -237,11 +237,8 @@ void clonedQueryShouldNotDependOnCriteriaFromSource() { source.addCriteria(where("From one make ten").is("and two let be.")); Query target = Query.of(source); - compareQueries(target, source); - source.addCriteria(where("Make even three").is("then rich you'll be.")); - - assertThat(target.getQueryObject()).isEqualTo(new Document("From one make ten", "and two let be.")) - .isNotEqualTo(source.getQueryObject()); + assertThat(target.getQueryObject()).containsAllEntriesOf(new Document("From one make ten", "and two let be.")) + .isNotSameAs(source.getQueryObject()); } @Test // DATAMONGO-1783 @@ -353,9 +350,12 @@ void queryOfShouldWorkOnProxiedObjects() { private void compareQueries(Query actual, Query expected) { assertThat(actual.getCollation()).isEqualTo(expected.getCollation()); - assertThat(actual.getSortObject()).isEqualTo(expected.getSortObject()); - assertThat(actual.getFieldsObject()).isEqualTo(expected.getFieldsObject()); - assertThat(actual.getQueryObject()).isEqualTo(expected.getQueryObject()); + assertThat(actual.getSortObject()).hasSameSizeAs(expected.getSortObject()) + .containsAllEntriesOf(expected.getSortObject()); + assertThat(actual.getFieldsObject()).hasSameSizeAs(expected.getFieldsObject()) + .containsAllEntriesOf(expected.getFieldsObject()); + assertThat(actual.getQueryObject()).hasSameSizeAs(expected.getQueryObject()) + .containsAllEntriesOf(expected.getQueryObject()); assertThat(actual.getHint()).isEqualTo(expected.getHint()); assertThat(actual.getLimit()).isEqualTo(expected.getLimit()); assertThat(actual.getSkip()).isEqualTo(expected.getSkip()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java index c6c1b140cd..9d8400995a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java @@ -31,11 +31,8 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; @@ -128,7 +125,7 @@ void propagatesRootExceptionForInvalidQuery() { @Test // DATAMONGO-1345, DATAMONGO-1735 void doesNotDeriveFieldSpecForNormalDomainType() { - assertThat(deriveQueryFromMethod("findPersonBy", new Object[0]).getFieldsObject()).isEqualTo(new Document()); + assertThat(deriveQueryFromMethod("findPersonBy", new Object[0]).getFieldsObject()).isEmpty(); } @Test // DATAMONGO-1345 @@ -173,7 +170,7 @@ void doesNotCreateFieldsObjectForOpenProjection() { org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findAllBy"); - assertThat(query.getFieldsObject()).isEqualTo(new Document()); + assertThat(query.getFieldsObject()).isEmpty(); } @Test // DATAMONGO-1865 From d70e459ffe821c4c3b44783ed162d6461732a05c Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 10 Sep 2021 10:48:22 +0200 Subject: [PATCH 0541/1381] Upgrade to MongoDB Java Drivers 4.3.2 Closes: #3816 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4aa47bbf2b..7cb1d10f85 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ multi spring-data-mongodb 2.6.0-SNAPSHOT - 4.3.1 + 4.3.2 ${mongo} 1.19 From 7d6b5ae5fee0ec48dc07f2abce3ab6d342076635 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 10 Sep 2021 15:37:59 +0200 Subject: [PATCH 0542/1381] Upgrade to Maven Wrapper 3.8.2. See #3818 --- .mvn/wrapper/maven-wrapper.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 00d32aab1d..39700a5c4b 100755 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip \ No newline at end of file +#Fri Sep 10 15:37:59 CEST 2021 +distributionUrl=https\://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip From e7150f525ed39ef565c56c45d9c1d965ce728c96 Mon Sep 17 00:00:00 2001 From: divyajnu08 Date: Fri, 10 Sep 2021 10:37:30 +0530 Subject: [PATCH 0543/1381] Fix update mapping using nested integer keys on map structures. Closes: #3775 Original Pull Request: #3815 --- .../mongodb/core/convert/QueryMapper.java | 5 ++-- .../core/convert/QueryMapperUnitTests.java | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 356dd89faa..df53f2c21c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -70,6 +70,7 @@ * @author Christoph Strobl * @author Mark Paluch * @author David Julia + * @author Divya Srivastava */ public class QueryMapper { @@ -1032,8 +1033,8 @@ public TypeInformation getTypeHint() { */ protected static class MetadataBackedField extends Field { - private static final Pattern POSITIONAL_PARAMETER_PATTERN = Pattern.compile("\\.\\$(\\[.*?\\])?|\\.\\d+"); - private static final Pattern DOT_POSITIONAL_PATTERN = Pattern.compile("\\.\\d+"); + private static final Pattern POSITIONAL_PARAMETER_PATTERN = Pattern.compile("\\.\\$(\\[.*?\\])?"); + private static final Pattern DOT_POSITIONAL_PATTERN = Pattern.compile("\\.\\d+(?!$)"); private static final String INVALID_ASSOCIATION_REFERENCE = "Invalid path reference %s! Associations can only be pointed to directly or via their id property!"; private final MongoPersistentEntity entity; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 46db6e7d6a..a54e80fa39 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -61,6 +61,7 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.TextQuery; +import org.springframework.data.mongodb.core.query.Update; import com.mongodb.BasicDBObject; import com.mongodb.MongoClientSettings; @@ -1354,6 +1355,25 @@ void mapStringIdFieldProjection() { org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1), context.getPersistentEntity(WithStringId.class)); assertThat(mappedFields).containsEntry("_id", 1); } + + @Test + void mapNestedStringFieldCorrectly() { + Update update = new Update(); + update.set("levelOne.a.b.d", "e"); + org.bson.Document document = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithNestedMap.class)); + assertThat(document).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.a.b.d","e"))); + } + + @Test + void mapNestedIntegerFieldCorrectly() { + Update update = new Update(); + update.set("levelOne.0.1.3", "4"); + org.bson.Document document = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithNestedMap.class)); + assertThat(document).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0.1.3","4"))); + } + @Test // GH-3783 void retainsId$InWithStringArray() { @@ -1542,6 +1562,11 @@ static class EntityWithIntKeyedMapOfMap{ static class EntityWithComplexValueTypeList { List list; } + + static class EntityWithNestedMap { + Map>> levelOne; + } + static class WithExplicitTargetTypes { From eda1c793157b8883441a43c7bcc629926a7e7206 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 13 Sep 2021 14:25:17 +0200 Subject: [PATCH 0544/1381] Move and add tests to UpdateMapper. Also update author information. Original Pull Request: #3815 --- .../core/convert/QueryMapperUnitTests.java | 24 -------- .../core/convert/UpdateMapperUnitTests.java | 55 +++++++++++++++++++ 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index a54e80fa39..11ea78fd4d 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1355,25 +1355,6 @@ void mapStringIdFieldProjection() { org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1), context.getPersistentEntity(WithStringId.class)); assertThat(mappedFields).containsEntry("_id", 1); } - - @Test - void mapNestedStringFieldCorrectly() { - Update update = new Update(); - update.set("levelOne.a.b.d", "e"); - org.bson.Document document = mapper.getMappedObject(update.getUpdateObject(), - context.getPersistentEntity(EntityWithNestedMap.class)); - assertThat(document).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.a.b.d","e"))); - } - - @Test - void mapNestedIntegerFieldCorrectly() { - Update update = new Update(); - update.set("levelOne.0.1.3", "4"); - org.bson.Document document = mapper.getMappedObject(update.getUpdateObject(), - context.getPersistentEntity(EntityWithNestedMap.class)); - assertThat(document).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0.1.3","4"))); - } - @Test // GH-3783 void retainsId$InWithStringArray() { @@ -1562,11 +1543,6 @@ static class EntityWithIntKeyedMapOfMap{ static class EntityWithComplexValueTypeList { List list; } - - static class EntityWithNestedMap { - Map>> levelOne; - } - static class WithExplicitTargetTypes { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index bba9811e56..44712fa8d1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -68,6 +68,7 @@ * @author Mark Paluch * @author Pavel Vodrazka * @author David Julia + * @author Divya Srivastava */ @ExtendWith(MockitoExtension.class) class UpdateMapperUnitTests { @@ -1200,6 +1201,56 @@ void mapsObjectClassPropertyFieldInMapValueTypeAsKey() { assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"map.class\": \"value\"}}"); } + @Test // GH-3775 + void mapNestedStringFieldCorrectly() { + + Update update = new Update().set("levelOne.a.b.d", "e"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithNestedMap.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.a.b.d","e"))); + } + + @Test // GH-3775 + void mapNestedIntegerFieldCorrectly() { + + Update update = new Update().set("levelOne.0.1.3", "4"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithNestedMap.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0.1.3","4"))); + } + + @Test // GH-3775 + void mapNestedMixedStringIntegerFieldCorrectly() { + + Update update = new Update().set("levelOne.0.1.c", "4"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithNestedMap.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0.1.c","4"))); + } + + @Test // GH-3775 + void mapNestedMixedStringIntegerWithStartNumberFieldCorrectly() { + + Update update = new Update().set("levelOne.0a.1b.3c", "4"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithNestedMap.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0a.1b.3c","4"))); + } + + @Test // GH-3688 + void multipleKeysStartingWithANumberInNestedPath() { + + Update update = new Update().set("intKeyedMap.1a.map.0b", "testing"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithIntKeyedMap.class)); + + assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"intKeyedMap.1a.map.0b\": \"testing\"}}"); + } + static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes { ListModelWrapper concreteTypeWithListAttributeOfInterfaceType; } @@ -1566,4 +1617,8 @@ static class UnwrappableType { String transientValue; } + static class EntityWithNestedMap { + Map>> levelOne; + } + } From 99203b397a27f9cd595eebb028161b9c054dfd68 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 24 Aug 2021 07:06:17 +0200 Subject: [PATCH 0545/1381] Add support for deriving json schema for encrypted properties. This commit introduces support for creating a MongoJsonSchema containing encrypted fields for a given type based on mapping metadata. Using the Encrypted annotation allows to derive required encryptMetadata and encrypt properties within a given (mapping)context. @Document @Encrypted(keyId = "...") static class Patient { // ... @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") private Integer ssn; } MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext); MongoJsonSchema patientSchema = schemaCreator .filter(MongoJsonSchemaCreator.encryptedOnly()) .createSchemaFor(Patient.class); Closes: #3800 Original pull request: #3801. --- .../mongodb/core/EncryptionAlgorithms.java | 29 ++ .../core/MappingMongoJsonSchemaCreator.java | 109 ++++++- .../mongodb/core/MongoJsonSchemaCreator.java | 136 +++++++++ .../mapping/BasicMongoPersistentEntity.java | 38 +++ .../mapping/BasicMongoPersistentProperty.java | 48 ++++ .../data/mongodb/core/mapping/Encrypted.java | 112 ++++++++ .../core/mapping/MongoMappingContext.java | 6 + .../core/mapping/MongoPersistentEntity.java | 9 + .../core/mapping/MongoPersistentProperty.java | 9 + .../UnwrappedMongoPersistentEntity.java | 6 + .../UnwrappedMongoPersistentProperty.java | 6 + .../core/schema/DefaultMongoJsonSchema.java | 36 ++- .../core/schema/DocumentJsonSchema.java | 6 +- .../IdentifiableJsonSchemaProperty.java | 16 +- .../mongodb/core/schema/MongoJsonSchema.java | 32 ++- .../core/schema/TypedJsonSchemaObject.java | 4 + .../util/encryption/EncryptionUtils.java | 67 +++++ .../mongodb/util/spel/ExpressionUtils.java | 52 ++++ ...appingMongoJsonSchemaCreatorUnitTests.java | 272 +++++++++++++++++- .../asciidoc/reference/mongo-json-schema.adoc | 103 +++++++ 20 files changed, 1074 insertions(+), 22 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Encrypted.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/encryption/EncryptionUtils.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/spel/ExpressionUtils.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java new file mode 100644 index 0000000000..0ed7340aa1 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EncryptionAlgorithms.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 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 + * + * https://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; + +/** + * Encryption algorithms supported by MongoDB Client Side Field Level Encryption. + * + * @author Christoph Strobl + * @since 3.3 + */ +public final class EncryptionAlgorithms { + + public static final String AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"; + public static final String AEAD_AES_256_CBC_HMAC_SHA_512_Random = "AEAD_AES_256_CBC_HMAC_SHA_512-Random"; + +} 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 ecbf8a4f07..a53ff8f5a5 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 @@ -20,13 +20,19 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import org.bson.Document; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.Encrypted; 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.EncryptedJsonSchemaProperty; import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ObjectJsonSchemaProperty; import org.springframework.data.mongodb.core.schema.JsonSchemaObject; import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type; @@ -34,10 +40,12 @@ 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; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; /** * {@link MongoJsonSchemaCreator} implementation using both {@link MongoConverter} and {@link MappingContext} to obtain @@ -52,6 +60,7 @@ class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator { private final MongoConverter converter; private final MappingContext, MongoPersistentProperty> mappingContext; + private final Predicate filter; /** * Create a new instance of {@link MappingMongoJsonSchemaCreator}. @@ -61,10 +70,24 @@ class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator { @SuppressWarnings("unchecked") MappingMongoJsonSchemaCreator(MongoConverter converter) { + this(converter, (MappingContext, MongoPersistentProperty>) converter.getMappingContext(), + (property) -> true); + } + + @SuppressWarnings("unchecked") + MappingMongoJsonSchemaCreator(MongoConverter converter, + MappingContext, MongoPersistentProperty> mappingContext, + Predicate filter) { + Assert.notNull(converter, "Converter must not be null!"); this.converter = converter; - this.mappingContext = (MappingContext, MongoPersistentProperty>) converter - .getMappingContext(); + this.mappingContext = mappingContext; + this.filter = filter; + } + + @Override + public MongoJsonSchemaCreator filter(Predicate filter) { + return new MappingMongoJsonSchemaCreator(converter, mappingContext, filter); } /* @@ -77,11 +100,29 @@ public MongoJsonSchema createSchemaFor(Class type) { MongoPersistentEntity entity = mappingContext.getRequiredPersistentEntity(type); MongoJsonSchemaBuilder schemaBuilder = MongoJsonSchema.builder(); + { + Encrypted encrypted = entity.findAnnotation(Encrypted.class); + if (encrypted != null) { + + Document encryptionMetadata = new Document(); + + Collection encryptionKeyIds = entity.getEncryptionKeyIds(); + if (!CollectionUtils.isEmpty(encryptionKeyIds)) { + encryptionMetadata.append("keyId", encryptionKeyIds); + } + + if (StringUtils.hasText(encrypted.algorithm())) { + encryptionMetadata.append("algorithm", encrypted.algorithm()); + } + + schemaBuilder.encryptionMetadata(encryptionMetadata); + } + } + List schemaProperties = computePropertiesForEntity(Collections.emptyList(), entity); schemaBuilder.properties(schemaProperties.toArray(new JsonSchemaProperty[0])); return schemaBuilder.build(); - } private List computePropertiesForEntity(List path, @@ -93,6 +134,11 @@ private List computePropertiesForEntity(List currentPath = new ArrayList<>(path); + if (!filter.test(new PropertyContext( + currentPath.stream().map(PersistentProperty::getName).collect(Collectors.joining(".")), nested))) { + continue; + } + if (path.contains(nested)) { // cycle guard schemaProperties.add(createSchemaProperty(computePropertyFieldName(CollectionUtils.lastElement(currentPath)), Object.class, false)); @@ -120,15 +166,38 @@ private JsonSchemaProperty computeSchemaForProperty(List path, @@ -207,4 +276,30 @@ static JsonSchemaProperty createPotentiallyRequiredSchemaProperty(JsonSchemaProp return JsonSchemaProperty.required(property); } + + class PropertyContext implements JsonSchemaPropertyContext { + + private String path; + private MongoPersistentProperty property; + + public PropertyContext(String path, MongoPersistentProperty property) { + this.path = path; + this.property = property; + } + + @Override + public String getPath() { + return path; + } + + @Override + public MongoPersistentProperty getProperty() { + return property; + } + + @Override + public MongoPersistentEntity resolveEntity(MongoPersistentProperty property) { + return (MongoPersistentEntity) mappingContext.getPersistentEntity(property); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java index f3c0dcd624..5e5bc50644 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java @@ -15,7 +15,23 @@ */ package org.springframework.data.mongodb.core; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.mapping.Encrypted; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes; +import org.springframework.data.mongodb.core.mapping.Unwrapped.Nullable; +import org.springframework.data.mongodb.core.schema.JsonSchemaProperty; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; import org.springframework.util.Assert; @@ -46,6 +62,7 @@ * {@link org.bson.types.ObjectId} like {@link String} will be mapped to {@code type : 'object'} unless there is more * specific information available via the {@link org.springframework.data.mongodb.core.mapping.MongoId} annotation. *

      + * {@link Encrypted} properties will contain {@literal encrypt} information. * * @author Christoph Strobl * @since 2.2 @@ -60,6 +77,88 @@ public interface MongoJsonSchemaCreator { */ MongoJsonSchema createSchemaFor(Class type); + /** + * Filter matching {@link JsonSchemaProperty properties}. + * + * @param filter the {@link Predicate} to evaluate for inclusion. Must not be {@literal null}. + * @return new instance of {@link MongoJsonSchemaCreator}. + * @since 3.3 + */ + MongoJsonSchemaCreator filter(Predicate filter); + + /** + * The context in which a specific {@link #getProperty()} is encountered during schema creation. + * + * @since 3.3 + */ + interface JsonSchemaPropertyContext { + + /** + * The path to a given field/property in dot notation. + * + * @return never {@literal null}. + */ + String getPath(); + + /** + * The current property. + * + * @return never {@literal null}. + */ + MongoPersistentProperty getProperty(); + + /** + * Obtain the {@link MongoPersistentEntity} for a given property. + * + * @param property must not be {@literal null}. + * @param + * @return {@literal null} if the property is not an entity. It is nevertheless recommend to check + * {@link PersistentProperty#isEntity()} first. + */ + @Nullable + MongoPersistentEntity resolveEntity(MongoPersistentProperty property); + + } + + /** + * A filter {@link Predicate} that matches {@link Encrypted encrypted properties} and those having nested ones. + * + * @return new instance of {@link Predicate}. + * @since 3.3 + */ + static Predicate encryptedOnly() { + + return new Predicate() { + + // cycle guard + private final Set seen = new HashSet<>(); + + @Override + public boolean test(JsonSchemaPropertyContext context) { + return extracted(context.getProperty(), context); + } + + private boolean extracted(MongoPersistentProperty property, JsonSchemaPropertyContext context) { + if (property.isAnnotationPresent(Encrypted.class)) { + return true; + } + + if (!property.isEntity() || seen.contains(property)) { + return false; + } + + seen.add(property); + + for (MongoPersistentProperty nested : context.resolveEntity(property)) { + if (extracted(nested, context)) { + return true; + } + } + return false; + } + }; + } + /** * Creates a new {@link MongoJsonSchemaCreator} that is aware of conversions applied by the given * {@link MongoConverter}. @@ -72,4 +171,41 @@ static MongoJsonSchemaCreator create(MongoConverter mongoConverter) { Assert.notNull(mongoConverter, "MongoConverter must not be null!"); return new MappingMongoJsonSchemaCreator(mongoConverter); } + + /** + * Creates a new {@link MongoJsonSchemaCreator} that is aware of type mappings and potential + * {@link org.springframework.data.spel.spi.EvaluationContextExtension extensions}. + * + * @param mappingContext must not be {@literal null}. + * @return new instance of {@link MongoJsonSchemaCreator}. + * @since 3.3 + */ + static MongoJsonSchemaCreator create(MappingContext mappingContext) { + + MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(config -> {})); + converter.afterPropertiesSet(); + + return create(converter); + } + + /** + * Creates a new {@link MongoJsonSchemaCreator} that does not consider potential extensions - suitable for testing. We + * recommend to use {@link #create(MappingContext)}. + * + * @return new instance of {@link MongoJsonSchemaCreator}. + * @since 3.3 + */ + static MongoJsonSchemaCreator create() { + + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.setSimpleTypeHolder(MongoSimpleTypes.HOLDER); + mappingContext.afterPropertiesSet(); + + MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext); + converter.setCustomConversions(MongoCustomConversions.create(config -> {})); + converter.afterPropertiesSet(); + + return create(converter); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index 7bf8214aeb..6840fce5bf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -17,8 +17,12 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.springframework.data.annotation.Id; @@ -28,6 +32,9 @@ import org.springframework.data.mapping.PropertyHandler; import org.springframework.data.mapping.model.BasicPersistentEntity; import org.springframework.data.mongodb.MongoCollectionUtils; +import org.springframework.data.mongodb.util.encryption.EncryptionUtils; +import org.springframework.data.spel.ExpressionDependencies; +import org.springframework.data.util.Lazy; import org.springframework.data.util.TypeInformation; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; @@ -212,6 +219,11 @@ public EvaluationContext getEvaluationContext(Object rootObject) { return super.getEvaluationContext(rootObject); } + @Override + public EvaluationContext getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) { + return super.getEvaluationContext(rootObject, dependencies); + } + private void verifyFieldUniqueness() { AssertFieldNameUniquenessHandler handler = new AssertFieldNameUniquenessHandler(); @@ -360,6 +372,32 @@ private void assertUniqueness(MongoPersistentProperty property) { } } + @Override + public Collection getEncryptionKeyIds() { + + Encrypted encrypted = findAnnotation(Encrypted.class); + if (encrypted == null) { + return null; + } + + if (ObjectUtils.isEmpty(encrypted.keyId())) { + return Collections.emptySet(); + } + + Lazy evaluationContext = Lazy.of(() -> { + + EvaluationContext ctx = getEvaluationContext(null); + ctx.setVariable("target", getType().getSimpleName()); + return ctx; + }); + + List target = new ArrayList<>(); + for (String keyId : encrypted.keyId()) { + target.add(EncryptionUtils.resolveKeyId(keyId, evaluationContext)); + } + return target; + } + /** * @author Christoph Strobl * @since 1.6 diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 1315757896..cf74d696a8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -16,7 +16,11 @@ package org.springframework.data.mongodb.core.mapping; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.bson.types.ObjectId; @@ -29,7 +33,12 @@ import org.springframework.data.mapping.model.Property; import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.mongodb.util.encryption.EncryptionUtils; +import org.springframework.data.util.Lazy; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -299,4 +308,43 @@ public boolean isTextScoreProperty() { return isAnnotationPresent(TextScore.class); } + /** + * Obtain the {@link EvaluationContext} for a specific root object. + * + * @param rootObject can be {@literal null}. + * @return never {@literal null}. + * @since 3.3 + */ + public EvaluationContext getEvaluationContext(@Nullable Object rootObject) { + + if (getOwner() instanceof BasicMongoPersistentEntity) { + return ((BasicMongoPersistentEntity) getOwner()).getEvaluationContext(rootObject); + } + return rootObject != null ? new StandardEvaluationContext(rootObject) : new StandardEvaluationContext(); + } + + @Override + public Collection getEncryptionKeyIds() { + + Encrypted encrypted = findAnnotation(Encrypted.class); + if (encrypted == null) { + return null; + } + + if (ObjectUtils.isEmpty(encrypted.keyId())) { + return Collections.emptySet(); + } + + Lazy evaluationContext = Lazy.of(() -> { + EvaluationContext ctx = getEvaluationContext(null); + ctx.setVariable("target", getOwner().getType().getSimpleName() + "." + getName()); + return ctx; + }); + + List target = new ArrayList<>(); + for (String keyId : encrypted.keyId()) { + target.add(EncryptionUtils.resolveKeyId(keyId, evaluationContext)); + } + return target; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Encrypted.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Encrypted.java new file mode 100644 index 0000000000..8bd0f99c41 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/Encrypted.java @@ -0,0 +1,112 @@ +/* + * Copyright 2021 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 + * + * https://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.mapping; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * {@link Encrypted} provides data required for MongoDB Client Side Field Level Encryption that is applied during schema + * resolution. It can be applied on top level (typically those types annotated with {@link Document} to provide the + * {@literal encryptMetadata}. + * + *
      + * @Document
      + * @Encrypted(keyId = "4fPYFM9qSgyRAjgQ2u+IMQ==")
      + * public class Patient {
      + * 	 private ObjectId id;
      + * 	 private String name;
      + *
      + * 	 @Field("publisher_ac")
      + * 	 @DocumentReference(lookup = "{ 'acronym' : ?#{#target} }") private Publisher publisher;
      + * }
      + *
      + * "encryptMetadata": {
      + *    "keyId": [
      + *      {
      + *        "$binary": {
      + *          "base64": "4fPYFM9qSgyRAjgQ2u+IMQ==",
      + *          "subType": "04"
      + *        }
      + *      }
      + *    ]
      + *  }
      + * 
      + * + *
      + * On property level it is used for deriving field specific {@literal encrypt} settings. + * + *
      + * public class Patient {
      + * 	 private ObjectId id;
      + * 	 private String name;
      + *
      + * 	 @Encrypted(keyId = "4fPYFM9qSgyRAjgQ2u+IMQ==", algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")
      + * 	 private String ssn;
      + * }
      + *
      + * "ssn" : {
      + *   "encrypt": {
      + *      "keyId": [
      + *        {
      + *          "$binary": {
      + *            "base64": "4fPYFM9qSgyRAjgQ2u+IMQ==",
      + *            "subType": "04"
      + *          }
      + *        }
      + *      ],
      + *      "algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
      + *      "bsonType" : "string"
      + *    }
      + *  }
      + * 
      + * + * @author Christoph Strobl + * @since 3.3 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.FIELD }) +public @interface Encrypted { + + /** + * Get the {@code keyId} to use. The value must resolve to either the UUID representation of the key or a base64 + * encoded value representing the UUID value. + *

      + * On {@link ElementType#TYPE} level the {@link #keyId()} can be left empty if explicitly set for fields.
      + * On {@link ElementType#FIELD} level the {@link #keyId()} can be left empty if inherited from + * {@literal encryptMetadata}. + * + * @return the key id to use. May contain a parsable {@link org.springframework.expression.Expression expression}. In + * this case the {@code #target} variable will hold the target element name. + */ + String[] keyId() default {}; + + /** + * Set the algorithm to use. + *

      + * On {@link ElementType#TYPE} level the {@link #algorithm()} can be left empty if explicitly set for fields.
      + * On {@link ElementType#FIELD} level the {@link #algorithm()} can be left empty if inherited from + * {@literal encryptMetadata}. + * + * @return the encryption algorithm. + * @see org.springframework.data.mongodb.core.EncryptionAlgorithms + */ + String algorithm() default ""; +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java index 121658b065..674ea74f3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java @@ -46,6 +46,9 @@ public class MongoMappingContext extends AbstractMappingContext BasicMongoPersistentEntity createPersistentEntity(TypeInformati */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + + this.applicationContext = applicationContext; super.setApplicationContext(applicationContext); } @@ -145,4 +150,5 @@ public MongoPersistentEntity getPersistentEntity(MongoPersistentProperty pers return new UnwrappedMongoPersistentEntity<>(entity, new UnwrapEntityContext(persistentProperty)); } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java index deb69eab36..d9b5ae0bd4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentEntity.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.mapping; +import java.util.Collection; + import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.model.MutablePersistentEntity; import org.springframework.lang.Nullable; @@ -102,4 +104,11 @@ default boolean isUnwrapped() { return false; } + /** + * @return the resolved encryption keyIds if applicable. An empty {@link Collection} if no keyIds specified. + * {@literal null} no {@link Encrypted} annotation found. + * @since 3.3 + */ + @Nullable + Collection getEncryptionKeyIds(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index 2bd387d74c..8dc89e03f9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.mapping; +import java.util.Collection; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.mapping.PersistentEntity; @@ -160,6 +162,13 @@ default boolean isUnwrapped() { return isEntity() && isAnnotationPresent(Unwrapped.class); } + /** + * @return the resolved encryption keyIds if applicable. An empty {@link Collection} if no keyIds specified. + * {@literal null} no {@link Encrypted} annotation found. + * @since 3.3 + */ + Collection getEncryptionKeyIds(); + /** * Simple {@link Converter} implementation to transform a {@link MongoPersistentProperty} into its field name. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentEntity.java index 6a60168e91..f85c73cae0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentEntity.java @@ -17,6 +17,7 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Spliterator; @@ -323,4 +324,9 @@ public void setEvaluationContextProvider(EvaluationContextProvider provider) { public boolean isUnwrapped() { return context.getProperty().isUnwrapped(); } + + @Override + public Collection getEncryptionKeyIds() { + return delegate.getEncryptionKeyIds(); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java index a2194c173f..24e4ae057f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/UnwrappedMongoPersistentProperty.java @@ -18,6 +18,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.Collection; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentEntity; @@ -268,6 +269,11 @@ public boolean isUnwrapped() { return delegate.isUnwrapped(); } + @Override + public Collection getEncryptionKeyIds() { + return delegate.getEncryptionKeyIds(); + } + @Override @Nullable public Class getComponentType() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java index 1b05840913..f77e4290ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java @@ -16,7 +16,9 @@ package org.springframework.data.mongodb.core.schema; import org.bson.Document; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; /** * Value object representing a MongoDB-specific JSON schema which is the default {@link MongoJsonSchema} implementation. @@ -29,18 +31,44 @@ class DefaultMongoJsonSchema implements MongoJsonSchema { private final JsonSchemaObject root; + @Nullable // + private final Document encryptionMetadata; + DefaultMongoJsonSchema(JsonSchemaObject root) { + this(root, null); + } + + /** + * Create new instance of {@link DefaultMongoJsonSchema}. + * + * @param root the schema root element. + * @param encryptionMetadata can be {@literal null}. + * @since 3.3 + */ + DefaultMongoJsonSchema(JsonSchemaObject root, @Nullable Document encryptionMetadata) { + + Assert.notNull(root, "Root schema object must not be null!"); - Assert.notNull(root, "Root must not be null!"); this.root = root; + this.encryptionMetadata = encryptionMetadata; } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.core.schema.MongoJsonSchema#toDocument() + * @see org.springframework.data.mongodb.core.schema.MongoJsonSchema#schema() */ @Override - public Document toDocument() { - return new Document("$jsonSchema", root.toDocument()); + public Document schemaDocument() { + + Document schemaDocument = new Document(); + + // we want this to be the first element rendered, so it reads nice when printed to json + if (!CollectionUtils.isEmpty(encryptionMetadata)) { + schemaDocument.append("encryptMetadata", encryptionMetadata); + } + + schemaDocument.putAll(root.toDocument()); + + return schemaDocument; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java index 2788dd59e5..787e94903a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java @@ -36,10 +36,10 @@ class DocumentJsonSchema implements MongoJsonSchema { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.core.schema.MongoJsonSchema#toDocument() + * @see org.springframework.data.mongodb.core.schema.MongoJsonSchema#schema() */ @Override - public Document toDocument() { - return new Document("$jsonSchema", new Document(document)); + public Document schemaDocument() { + return new Document(document); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java index 28116e1bac..97b3cc6b46 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java @@ -523,6 +523,10 @@ public ObjectJsonSchemaProperty description(String description) { public ObjectJsonSchemaProperty generatedDescription() { return new ObjectJsonSchemaProperty(identifier, jsonSchemaObjectDelegate.generatedDescription()); } + + public List getProperties() { + return jsonSchemaObjectDelegate.getProperties(); + } } /** @@ -1060,7 +1064,7 @@ public static class EncryptedJsonSchemaProperty implements JsonSchemaProperty { private final JsonSchemaProperty targetProperty; private final @Nullable String algorithm; private final @Nullable String keyId; - private final @Nullable List keyIds; + private final @Nullable List keyIds; /** * Create new instance of {@link EncryptedJsonSchemaProperty} wrapping the given {@link JsonSchemaProperty target}. @@ -1072,7 +1076,7 @@ public EncryptedJsonSchemaProperty(JsonSchemaProperty target) { } private EncryptedJsonSchemaProperty(JsonSchemaProperty target, @Nullable String algorithm, @Nullable String keyId, - @Nullable List keyIds) { + @Nullable List keyIds) { Assert.notNull(target, "Target must not be null!"); this.targetProperty = target; @@ -1134,6 +1138,14 @@ public EncryptedJsonSchemaProperty keys(UUID... keyId) { return new EncryptedJsonSchemaProperty(targetProperty, algorithm, null, Arrays.asList(keyId)); } + /** + * @param keyId must not be {@literal null}. + * @return new instance of {@link EncryptedJsonSchemaProperty}. + */ + public EncryptedJsonSchemaProperty keys(Object... keyId) { + return new EncryptedJsonSchemaProperty(targetProperty, algorithm, null, Arrays.asList(keyId)); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.schema.JsonSchemaObject#toDocument() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java index d45dcd09ec..a14cde2d3a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/MongoJsonSchema.java @@ -20,6 +20,7 @@ import org.bson.Document; import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.ObjectJsonSchemaObject; +import org.springframework.lang.Nullable; /** * Interface defining MongoDB-specific JSON schema object. New objects can be built with {@link #builder()}, for @@ -62,13 +63,25 @@ public interface MongoJsonSchema { /** - * Create the {@link Document} containing the specified {@code $jsonSchema}.
      + * Create the {@code $jsonSchema} {@link Document} containing the specified {@link #schemaDocument()}.
      * Property and field names need to be mapped to the domain type ones by running the {@link Document} through a * {@link org.springframework.data.mongodb.core.convert.JsonSchemaMapper} to apply field name customization. * * @return never {@literal null}. */ - Document toDocument(); + default Document toDocument() { + return new Document("$jsonSchema", schemaDocument()); + } + + /** + * Create the {@link Document} defining the schema.
      + * Property and field names need to be mapped to the domain type ones by running the {@link Document} through a + * {@link org.springframework.data.mongodb.core.convert.JsonSchemaMapper} to apply field name customization. + * + * @return never {@literal null}. + * @since 3.3 + */ + Document schemaDocument(); /** * Create a new {@link MongoJsonSchema} for a given root object. @@ -108,6 +121,9 @@ class MongoJsonSchemaBuilder { private ObjectJsonSchemaObject root; + @Nullable // + private Document encryptionMetadata; + MongoJsonSchemaBuilder() { root = new ObjectJsonSchemaObject(); } @@ -266,13 +282,23 @@ public MongoJsonSchemaBuilder description(String description) { return this; } + /** + * Define the {@literal encryptMetadata} element of the schema. + * + * @param encryptionMetadata can be {@literal null}. + * @since 3.3 + */ + public void encryptionMetadata(@Nullable Document encryptionMetadata) { + this.encryptionMetadata = encryptionMetadata; + } + /** * Obtain the {@link MongoJsonSchema}. * * @return new instance of {@link MongoJsonSchema}. */ public MongoJsonSchema build() { - return MongoJsonSchema.of(root); + return new DefaultMongoJsonSchema(root, encryptionMetadata); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java index 2486e98e08..59a367a9d7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/TypedJsonSchemaObject.java @@ -437,6 +437,10 @@ public ObjectJsonSchemaObject generatedDescription() { return newInstance(description, true, restrictions); } + public List getProperties() { + return properties; + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.schema.JsonSchemaObject#toDocument() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/encryption/EncryptionUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/encryption/EncryptionUtils.java new file mode 100644 index 0000000000..809f83fdc9 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/encryption/EncryptionUtils.java @@ -0,0 +1,67 @@ +/* + * Copyright 2021 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 + * + * https://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.util.encryption; + +import java.util.UUID; +import java.util.function.Supplier; + +import org.springframework.data.mongodb.util.spel.ExpressionUtils; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Internal utility class for dealing with encryption related matters. + * + * @author Christoph Strobl + * @since 3.3 + */ +public final class EncryptionUtils { + + /** + * Resolve a given plain {@link String} value into the store native {@literal keyId} format, considering potential + * {@link Expression expressions}.
      + * The potential keyId is probed against an {@link UUID#fromString(String) UUID value} and the {@literal base64} + * encoded {@code $binary} representation. + * + * @param value the source value to resolve the keyId for. Must not be {@literal null}. + * @param evaluationContext a {@link Supplier} used to provide the {@link EvaluationContext} in case an + * {@link Expression} is {@link ExpressionUtils#detectExpression(String) detected}. + * @return can be {@literal null}. + * @throws IllegalArgumentException if one of the required arguments is {@literal null}. + */ + @Nullable + public static Object resolveKeyId(String value, Supplier evaluationContext) { + + Assert.notNull(value, "Value must not be null!"); + + Object potentialKeyId = value; + Expression expression = ExpressionUtils.detectExpression(value); + if (expression != null) { + potentialKeyId = expression.getValue(evaluationContext.get()); + if (!(potentialKeyId instanceof String)) { + return potentialKeyId; + } + } + try { + return UUID.fromString(potentialKeyId.toString()); + } catch (IllegalArgumentException e) { + return org.bson.Document.parse("{ val : { $binary : { base64 : '" + potentialKeyId + "', subType : '04'} } }") + .get("val"); + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/spel/ExpressionUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/spel/ExpressionUtils.java new file mode 100644 index 0000000000..b41961e6ea --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/spel/ExpressionUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021 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 + * + * https://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.util.spel; + +import org.springframework.expression.Expression; +import org.springframework.expression.ParserContext; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +/** + * Internal utility class for dealing with {@link Expression} and potential ones. + * + * @author Christoph Strobl + * @since 3.3 + */ +public final class ExpressionUtils { + + private static final SpelExpressionParser PARSER = new SpelExpressionParser(); + + /** + * Returns a SpEL {@link Expression} if the given {@link String} is actually an expression that does not evaluate to a + * {@link LiteralExpression} (indicating that no subsequent evaluation is necessary). + * + * @param potentialExpression can be {@literal null} + * @return can be {@literal null}. + */ + @Nullable + public static Expression detectExpression(@Nullable String potentialExpression) { + + if (!StringUtils.hasText(potentialExpression)) { + return null; + } + + Expression expression = PARSER.parseExpression(potentialExpression, ParserContext.TEMPLATE_EXPRESSION); + return expression instanceof LiteralExpression ? null : expression; + } +} 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 9c52bbe628..9fd19189ce 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 @@ -19,23 +19,27 @@ import java.util.Collections; import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - +import org.springframework.context.support.GenericApplicationContext; import org.springframework.data.annotation.Transient; import org.springframework.data.convert.WritingConverter; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver; +import org.springframework.data.mongodb.core.mapping.Encrypted; import org.springframework.data.mongodb.core.mapping.Field; 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.data.spel.spi.EvaluationContextExtension; +import org.springframework.data.spel.spi.Function; /** * Unit tests for {@link MappingMongoJsonSchemaCreator}. @@ -95,6 +99,64 @@ public void converterRegistered() { "{ 'type' : 'object', 'properties' : { '_id' : { 'type' : 'object' }, 'nested' : { 'type' : 'object' } } }"); } + @Test // GH-3800 + public void csfle/*encryptedFieldsOnly*/() { + + MongoJsonSchema schema = MongoJsonSchemaCreator.create() // + .filter(MongoJsonSchemaCreator.encryptedOnly()) // filter non encrypted fields + .createSchemaFor(Patient.class); + + Document targetSchema = schema.schemaDocument(); + assertThat(targetSchema).isEqualTo(Document.parse(PATIENT)); + } + + @Test // GH-3800 + public void csfleCyclic/*encryptedFieldsOnly*/() { + + MongoJsonSchema schema = MongoJsonSchemaCreator.create() // + .filter(MongoJsonSchemaCreator.encryptedOnly()) // filter non encrypted fields + .createSchemaFor(Cyclic.class); + + Document targetSchema = schema.schemaDocument(); + assertThat(targetSchema).isNotNull(); + } + + @Test // GH-3800 + public void csfleWithKeyFromProperties() { + + GenericApplicationContext applicationContext = new GenericApplicationContext(); + applicationContext.registerBean("encryptionExtension", EncryptionExtension.class, () -> new EncryptionExtension()); + applicationContext.refresh(); + + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.setApplicationContext(applicationContext); + mappingContext.afterPropertiesSet(); + + MongoJsonSchema schema = MongoJsonSchemaCreator.create(mappingContext) // + .filter(MongoJsonSchemaCreator.encryptedOnly()) // + .createSchemaFor(EncryptionMetadataFromProperty.class); + + assertThat(schema.schemaDocument()).isEqualTo(Document.parse(ENC_FROM_PROPERTY_SCHEMA)); + } + + @Test // GH-3800 + public void csfleWithKeyFromMethod() { + + GenericApplicationContext applicationContext = new GenericApplicationContext(); + applicationContext.registerBean("encryptionExtension", EncryptionExtension.class, () -> new EncryptionExtension()); + applicationContext.refresh(); + + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.setApplicationContext(applicationContext); + mappingContext.afterPropertiesSet(); + + MongoJsonSchema schema = MongoJsonSchemaCreator.create(mappingContext) // + .filter(MongoJsonSchemaCreator.encryptedOnly()) // + .createSchemaFor(EncryptionMetadataFromMethod.class); + + assertThat(schema.schemaDocument()).isEqualTo(Document.parse(ENC_FROM_METHOD_SCHEMA)); + } + // --> TYPES AND JSON // --> ENUM @@ -125,8 +187,7 @@ enum JustSomeEnum { " 'collectionProperty' : { 'type' : 'array' }," + // " 'mapProperty' : { 'type' : 'object' }," + // " 'objectProperty' : { 'type' : 'object' }," + // - " 'enumProperty' : " + JUST_SOME_ENUM + // - " }" + // + " 'enumProperty' : " + JUST_SOME_ENUM + " }" + // "}"; static class VariousFieldTypes { @@ -249,4 +310,209 @@ public org.bson.Document convert(VariousFieldTypes source) { } } + static final String PATIENT = "{" + // + " 'type': 'object'," + // + " 'encryptMetadata': {" + // + " 'keyId': [" + // + " {" + // + " '$binary': {" + // + " 'base64': 'xKVup8B1Q+CkHaVRx+qa+g=='," + // + " 'subType': '04'" + // + " }" + // + " }" + // + " ]" + // + " }," + // + " 'properties': {" + // + " 'ssn': {" + // + " 'encrypt': {" + // + " 'bsonType': 'int'," + // + " 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'" + // + " }" + // + " }," + // + " 'bloodType': {" + // + " 'encrypt': {" + // + " 'bsonType': 'string'," + // + " 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'" + // + " }" + // + " }," + // + " 'medicalRecords': {" + // + " 'encrypt': {" + // + " 'bsonType': 'array'," + // + " 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'" + // + " }" + // + " }," + // + " 'insurance': {" + // + " 'type': 'object'," + // + " 'properties': {" + // + " 'policyNumber': {" + // + " 'encrypt': {" + // + " 'bsonType': 'int'," + // + " 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'" + // + " }" + // + " }" + // + " }" + // + " }" + // + " }" + // + "}"; + + @Encrypted(keyId = "xKVup8B1Q+CkHaVRx+qa+g==") + static class Patient { + String name; + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") // + Integer ssn; + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Random") // + String bloodType; + + String keyAltNameField; + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Random") // + List> medicalRecords; + + Insurance insurance; + } + + static class Insurance { + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") // + Integer policyNumber; + + String provider; + } + + static final String ENC_FROM_PROPERTY_ENTITY_KEY = "C5a5aMB7Ttq4wSJTFeRn8g=="; + static final String ENC_FROM_PROPERTY_PROPOERTY_KEY = "Mw6mdTVPQfm4quqSCLVB3g="; + static final String ENC_FROM_PROPERTY_SCHEMA = "{" + // + " 'encryptMetadata': {" + // + " 'keyId': [" + // + " {" + // + " '$binary': {" + // + " 'base64': '" + ENC_FROM_PROPERTY_ENTITY_KEY + "'," + // + " 'subType': '04'" + // + " }" + // + " }" + // + " ]" + // + " }," + // + " 'type': 'object'," + // + " 'properties': {" + // + " 'policyNumber': {" + // + " 'encrypt': {" + // + " 'keyId': [" + // + " [" + // + " {" + // + " '$binary': {" + // + " 'base64': '" + ENC_FROM_PROPERTY_PROPOERTY_KEY + "'," + // + " 'subType': '04'" + // + " }" + // + " }" + // + " ]" + // + " ]," + // + " 'bsonType': 'int'," + // + " 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'" + // + " }" + // + " }" + // + " }" + // + "}"; + + @Encrypted(keyId = "#{entityKey}") + static class EncryptionMetadataFromProperty { + + @Encrypted(keyId = "#{propertyKey}", algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") // + Integer policyNumber; + + String provider; + } + + static final String ENC_FROM_METHOD_ENTITY_KEY = "4fPYFM9qSgyRAjgQ2u+IMQ=="; + static final String ENC_FROM_METHOD_PROPOERTY_KEY = "+idiseKwTVCJfSKC3iUeYQ=="; + static final String ENC_FROM_METHOD_SCHEMA = "{" + // + " 'encryptMetadata': {" + // + " 'keyId': [" + // + " {" + // + " '$binary': {" + // + " 'base64': '" + ENC_FROM_METHOD_ENTITY_KEY + "'," + // + " 'subType': '04'" + // + " }" + // + " }" + // + " ]" + // + " }," + // + " 'type': 'object'," + // + " 'properties': {" + // + " 'policyNumber': {" + // + " 'encrypt': {" + // + " 'keyId': [" + // + " [" + // + " {" + // + " '$binary': {" + // + " 'base64': '" + ENC_FROM_METHOD_PROPOERTY_KEY + "'," + // + " 'subType': '04'" + // + " }" + // + " }" + // + " ]" + // + " ]," + // + " 'bsonType': 'int'," + // + " 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'" + // + " }" + // + " }" + // + " }" + // + "}"; + + @Encrypted(keyId = "#{mongocrypt.keyId(#target)}") + static class EncryptionMetadataFromMethod { + + @Encrypted(keyId = "#{mongocrypt.keyId(#target)}", algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") // + Integer policyNumber; + + String provider; + } + + public static class EncryptionExtension implements EvaluationContextExtension { + + /* + * (non-Javadoc) + * @see org.springframework.data.spel.spi.EvaluationContextExtension#getExtensionId() + */ + @Override + public String getExtensionId() { + return "mongocrypt"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.spel.spi.EvaluationContextExtension#getProperties() + */ + @Override + public Map getProperties() { + + Map properties = new LinkedHashMap<>(); + properties.put("entityKey", ENC_FROM_PROPERTY_ENTITY_KEY); + properties.put("propertyKey", ENC_FROM_PROPERTY_PROPOERTY_KEY); + return properties; + } + + @Override + public Map getFunctions() { + try { + return Collections.singletonMap("keyId", + new Function(EncryptionExtension.class.getMethod("keyId", String.class), this)); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + return Collections.emptyMap(); + } + + public String keyId(String target) { + + if (target.equals("EncryptionMetadataFromMethod")) { + return ENC_FROM_METHOD_ENTITY_KEY; + } + + if (target.equals("EncryptionMetadataFromMethod.policyNumber")) { + return ENC_FROM_METHOD_PROPOERTY_KEY; + } + + return "xKVup8B1Q+CkHaVRx+qa+g=="; + } + } } diff --git a/src/main/asciidoc/reference/mongo-json-schema.adoc b/src/main/asciidoc/reference/mongo-json-schema.adoc index 5a426061a2..36c85f6fb5 100644 --- a/src/main/asciidoc/reference/mongo-json-schema.adoc +++ b/src/main/asciidoc/reference/mongo-json-schema.adoc @@ -225,6 +225,109 @@ MongoJsonSchema schema = MongoJsonSchema.builder() ---- ==== +Instead of defining encrypted fields manually it is possible leverage the `@Encrypted` annotation as shown in the snippet below. + +.Client-Side Field Level Encryption via Json Schema +==== +[source,java] +---- +@Document +@Encrypted(keyId = "xKVup8B1Q+CkHaVRx+qa+g==", algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Random") <1> +static class Patient { + + @Id String id; + String name; + + @Encrypted <2> + String bloodType; + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") <3> + Integer ssn; +} +---- +<1> Default encryption settings that will be set for `encryptMetadata`. +<2> Encrypted field using default encryption settings. +<3> Encrypted field overriding the default encryption algorithm. +==== + +[TIP] +==== +The `@Encrypted` Annoation supports resolving keyIds via SpEL Expressions. +To do so additional environment metadata (via the `MappingContext`) is required and must be provided. + +[source,java] +---- +@Document +@Encrypted(keyId = "#{mongocrypt.keyId(#target)}") +static class Patient { + + @Id String id; + String name; + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Random") + String bloodType; + + @Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") + Integer ssn; +} + +MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext); +MongoJsonSchema patientSchema = schemaCreator + .filter(MongoJsonSchemaCreator.encryptedOnly()) + .createSchemaFor(Patient.class); +---- + +The `mongocrypt.keyId` function is defined via an `EvaluationContextExtension` as shown in the snippet below. +Providing a custom extension provides the most flexible way of computing keyIds. + +[source,java] +---- +public class EncryptionExtension implements EvaluationContextExtension { + + @Override + public String getExtensionId() { + return "mongocrypt"; + } + + @Override + public Map getFunctions() { + return Collections.singletonMap("keyId", new Function(getMethod("computeKeyId", String.class), this)); + } + + public String computeKeyId(String target) { + // ... lookup via target element name + } +} +---- + +To combine derived encryption settings with `AutoEncryptionSettings` in a Spring Boot application use the `MongoClientSettingsBuilderCustomizer`. + +[source,java] +---- +@Bean +MongoClientSettingsBuilderCustomizer customizer(MappingContext mappingContext) { + return (builder) -> { + + // ... keyVaultCollection, kmsProvider, ... + + MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext); + MongoJsonSchema patientSchema = schemaCreator + .filter(MongoJsonSchemaCreator.encryptedOnly()) + .createSchemaFor(Patient.class); + + AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() + .keyVaultNamespace(keyVaultCollection) + .kmsProviders(kmsProviders) + .extraOptions(extraOpts) + .schemaMap(Collections.singletonMap("db.patient", patientSchema.schemaDocument().toBsonDocument())) + .build(); + + builder.autoEncryptionSettings(autoEncryptionSettings); + }; +} +---- +==== + NOTE: Make sure to set the drivers `com.mongodb.AutoEncryptionSettings` to use client-side encryption. MongoDB does not support encryption for all field types. Specific data types require deterministic encryption to preserve equality comparison functionality. [[mongo.jsonSchema.types]] From 9b02897db54cbd3b9edca34d4f48c2846d903499 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 13 Sep 2021 11:12:12 +0200 Subject: [PATCH 0546/1381] Add configuration support for MongoDB ServerApiVersion. Introduce FactoryBean and required options to set the ServerAPI. Update namespace xsd and parsing. Closes: #3820 Original pull request: #3821. --- .../mongodb/config/MongoParsingUtils.java | 17 + .../core/MongoClientSettingsFactoryBean.java | 17 +- .../core/MongoServerApiFactoryBean.java | 92 ++ .../main/resources/META-INF/spring.schemas | 6 +- .../data/mongodb/config/spring-mongo-3.3.xsd | 895 ++++++++++++++++++ .../config/MongoClientNamespaceTests.java | 13 + .../core/MongoServerApiFactoryBeanTests.java | 73 ++ .../MongoClientNamespaceTests-context.xml | 5 + 8 files changed, 1114 insertions(+), 4 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java create mode 100644 spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.3.xsd create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index cd4d16d91b..935be95500 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -22,9 +22,12 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.CustomEditorConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionValidationException; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.data.mongodb.core.MongoClientSettingsFactoryBean; +import org.springframework.data.mongodb.core.MongoServerApiFactoryBean; +import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -112,6 +115,20 @@ public static boolean parseMongoClientSettings(Element element, BeanDefinitionBu // Field level encryption setPropertyReference(clientOptionsDefBuilder, settingsElement, "encryption-settings-ref", "autoEncryptionSettings"); + // ServerAPI + if (StringUtils.hasText(settingsElement.getAttribute("server-api-version"))) { + + MongoServerApiFactoryBean serverApiFactoryBean = new MongoServerApiFactoryBean(); + serverApiFactoryBean.setVersion(settingsElement.getAttribute("server-api-version")); + try { + clientOptionsDefBuilder.addPropertyValue("serverApi", serverApiFactoryBean.getObject()); + } catch (Exception exception) { + throw new BeanDefinitionValidationException("Non parsable server-api.", exception); + } + } else { + setPropertyReference(clientOptionsDefBuilder, settingsElement, "server-api-ref", "serverApi"); + } + // and the rest mongoClientBuilder.addPropertyValue("mongoClientSettings", clientOptionsDefBuilder.getBeanDefinition()); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java index 162035a45d..818dd45f3f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java @@ -36,6 +36,7 @@ import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; import com.mongodb.ServerAddress; +import com.mongodb.ServerApi; import com.mongodb.WriteConcern; import com.mongodb.connection.ClusterConnectionMode; import com.mongodb.connection.ClusterType; @@ -113,6 +114,7 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean getObjectType() { return MongoClientSettings.class; @@ -476,9 +487,11 @@ protected MongoClientSettings createInstance() { if (retryWrites != null) { builder = builder.retryWrites(retryWrites); } - if (uUidRepresentation != null) { - builder.uuidRepresentation(uUidRepresentation); + builder = builder.uuidRepresentation(uUidRepresentation); + } + if (serverApi != null) { + builder = builder.serverApi(serverApi); } return builder.build(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java new file mode 100644 index 0000000000..e2a2fecaec --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java @@ -0,0 +1,92 @@ +/* + * Copyright 2021 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 + * + * https://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 org.springframework.beans.factory.FactoryBean; +import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; + +import com.mongodb.ServerApi; +import com.mongodb.ServerApi.Builder; +import com.mongodb.ServerApiVersion; + +/** + * {@link FactoryBean} for creating {@link ServerApi} using the {@link ServerApi.Builder}. + * + * @author Christoph Strobl + * @since 3.3 + */ +public class MongoServerApiFactoryBean implements FactoryBean { + + private String version; + private @Nullable Boolean deprecationErrors; + private @Nullable Boolean strict; + + /** + * @param version the version string either as the enum name or the server version value. + * @see ServerApiVersion + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * @param deprecationErrors + * @see ServerApi.Builder#deprecationErrors(boolean) + */ + public void setDeprecationErrors(@Nullable Boolean deprecationErrors) { + this.deprecationErrors = deprecationErrors; + } + + /** + * @param strict + * @see ServerApi.Builder#strict(boolean) + */ + public void setStrict(@Nullable Boolean strict) { + this.strict = strict; + } + + @Nullable + @Override + public ServerApi getObject() throws Exception { + + Builder builder = ServerApi.builder().version(version()); + + if (deprecationErrors != null) { + builder = builder.deprecationErrors(deprecationErrors); + } + if (strict != null) { + builder = builder.strict(strict); + } + return builder.build(); + } + + @Nullable + @Override + public Class getObjectType() { + return ServerApi.class; + } + + private ServerApiVersion version() { + try { + // lookup by name eg. 'V1' + return ObjectUtils.caseInsensitiveValueOf(ServerApiVersion.values(), version); + } catch (IllegalArgumentException e) { + // or just the version number, eg. just '1' + return ServerApiVersion.findByValue(version); + } + } +} diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index 1ebb3098c7..c7f3f0ab7b 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -11,7 +11,8 @@ http\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.2.xsd=org/sp http\://www.springframework.org/schema/data/mongo/spring-mongo-2.0.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-2.2.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-3.0.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd -http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo-3.3.xsd=org/springframework/data/mongodb/config/spring-mongo-3.3.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.3.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd @@ -25,4 +26,5 @@ https\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.2.xsd=org/s https\://www.springframework.org/schema/data/mongo/spring-mongo-2.0.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-2.2.xsd=org/springframework/data/mongodb/config/spring-mongo-2.2.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-3.0.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd -https\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +https\://www.springframework.org/schema/data/mongo/spring-mongo-3.3.xsd=org/springframework/data/mongodb/config/spring-mongo-3.3.xsd +https\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.3.xsd diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.3.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.3.xsd new file mode 100644 index 0000000000..80811306f1 --- /dev/null +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.3.xsd @@ -0,0 +1,895 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDatabaseFactory for a DB object + + + + + + + + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Enables creation of indexes for queries that get derived from the method name + and thus reference domain class properties. Defaults to false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a MongoDatabaseFactory. + + + + + + + + + + + + The reference to a MongoTypeMapper to be used by this MappingMongoConverter. + + + + + + + The reference to a MappingContext. Will default to 'mappingContext'. + + + + + + + Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false. + + + + + + + + + + Enables abbreviating the field names for domain class properties to the + first character of their camel case names, e.g. fooBar -> fb. Defaults to false. + + + + + + + + + + The reference to a FieldNamingStrategy. + + + + + + + Enable/Disable index creation for annotated properties/entities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A reference to a custom converter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a MongoDatabaseFactory. + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDatabaseFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a MongoDatabaseFactory. + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java index 47dd85e07a..abdd00c2b5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; +import com.mongodb.ServerApiVersion; import org.bson.UuidRepresentation; import org.junit.Test; import org.junit.runner.RunWith; @@ -147,4 +148,16 @@ public void clientWithUUidSettings() { MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); assertThat(settings.getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD); } + + @Test // DATAMONGO-2427 + public void clientWithServerVersion() { + + assertThat(ctx.containsBean("client-with-server-api-settings")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-server-api-settings", MongoClientFactoryBean.class); + + MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); + assertThat(settings.getServerApi()).isNotNull().satisfies(it -> { + assertThat(it.getVersion()).isEqualTo(ServerApiVersion.V1); + }); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java new file mode 100644 index 0000000000..0c79478fee --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021 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 + * + * https://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.*; + +import com.mongodb.ServerApi; +import com.mongodb.ServerApiVersion; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.test.util.ReflectionTestUtils; + +import com.mongodb.AutoEncryptionSettings; + +/** + * Integration tests for {@link MongoServerApiFactoryBean}. + * + * @author Christoph Strobl + */ +public class MongoServerApiFactoryBeanTests { + + @Test // DATAMONGO-2306 + public void createsServerApiForVersionString() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoServerApiFactoryBean.class); + definition.getPropertyValues().addPropertyValue("version", "V1"); + definition.getPropertyValues().addPropertyValue("deprecationErrors", "true"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerBeanDefinition("factory", definition); + + MongoServerApiFactoryBean bean = factory.getBean("&factory", MongoServerApiFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "deprecationErrors")).isEqualTo(true); + + ServerApi target = factory.getBean(ServerApi.class); + assertThat(target.getVersion()).isEqualTo(ServerApiVersion.V1); + assertThat(target.getDeprecationErrors()).contains(true); + assertThat(target.getStrict()).isNotPresent(); + } + + @Test // DATAMONGO-2306 + public void createsServerApiForVersionNumber() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoServerApiFactoryBean.class); + definition.getPropertyValues().addPropertyValue("version", "1"); + definition.getPropertyValues().addPropertyValue("strict", "true"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerBeanDefinition("factory", definition); + + MongoServerApiFactoryBean bean = factory.getBean("&factory", MongoServerApiFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "strict")).isEqualTo(true); + + ServerApi target = factory.getBean(ServerApi.class); + assertThat(target.getVersion()).isEqualTo(ServerApiVersion.V1); + assertThat(target.getDeprecationErrors()).isNotPresent(); + assertThat(target.getStrict()).contains(true); + } +} diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml index 1bd3aa2a05..79e5ac40a0 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml @@ -41,4 +41,9 @@ + + + + + From 0af8d6839e965b04717aa17f483a70af13c23a52 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 14 Sep 2021 09:11:32 +0200 Subject: [PATCH 0547/1381] Polishing. Reformat code, fix ticket references in tests. See #3820 Original pull request: #3821. --- .../mongodb/core/MongoServerApiFactoryBean.java | 2 +- .../config/MongoClientNamespaceTests.java | 5 +++-- .../core/MongoServerApiFactoryBeanTests.java | 16 ++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java index e2a2fecaec..c93016b097 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBean.java @@ -35,7 +35,7 @@ public class MongoServerApiFactoryBean implements FactoryBean { private @Nullable Boolean deprecationErrors; private @Nullable Boolean strict; - /** + /** * @param version the version string either as the enum name or the server version value. * @see ServerApiVersion */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java index abdd00c2b5..127e3d1022 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java @@ -21,10 +21,10 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; -import com.mongodb.ServerApiVersion; import org.bson.UuidRepresentation; import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.core.MongoClientFactoryBean; @@ -35,6 +35,7 @@ import com.mongodb.MongoClientSettings; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; +import com.mongodb.ServerApiVersion; import com.mongodb.connection.ClusterType; /** @@ -149,7 +150,7 @@ public void clientWithUUidSettings() { assertThat(settings.getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD); } - @Test // DATAMONGO-2427 + @Test // GH-3820 public void clientWithServerVersion() { assertThat(ctx.containsBean("client-with-server-api-settings")).isTrue(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java index 0c79478fee..d584b6cfb3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoServerApiFactoryBeanTests.java @@ -17,24 +17,24 @@ import static org.assertj.core.api.Assertions.*; -import com.mongodb.ServerApi; -import com.mongodb.ServerApiVersion; import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.AutoEncryptionSettings; +import com.mongodb.ServerApi; +import com.mongodb.ServerApiVersion; /** * Integration tests for {@link MongoServerApiFactoryBean}. * * @author Christoph Strobl */ -public class MongoServerApiFactoryBeanTests { +class MongoServerApiFactoryBeanTests { - @Test // DATAMONGO-2306 - public void createsServerApiForVersionString() { + @Test // GH-3820 + void createsServerApiForVersionString() { RootBeanDefinition definition = new RootBeanDefinition(MongoServerApiFactoryBean.class); definition.getPropertyValues().addPropertyValue("version", "V1"); @@ -52,8 +52,8 @@ public void createsServerApiForVersionString() { assertThat(target.getStrict()).isNotPresent(); } - @Test // DATAMONGO-2306 - public void createsServerApiForVersionNumber() { + @Test // GH-3820 + void createsServerApiForVersionNumber() { RootBeanDefinition definition = new RootBeanDefinition(MongoServerApiFactoryBean.class); definition.getPropertyValues().addPropertyValue("version", "1"); From 8f00ffd29158ff2294a08f8e4ec3c5e8ab45e9ab Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 15 Sep 2021 15:30:10 +0200 Subject: [PATCH 0548/1381] Change visibility of PersistentEntitiesFactoryBean. Closes: #3825 --- .../data/mongodb/config/PersistentEntitiesFactoryBean.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java index ba382a32cc..29d606c4de 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java @@ -28,7 +28,7 @@ * @author Christoph Strobl * @since 3.1 */ -class PersistentEntitiesFactoryBean implements FactoryBean { +public class PersistentEntitiesFactoryBean implements FactoryBean { private final MappingMongoConverter converter; From 38e1d0d92deb9a2d0009abf335e67b6fef74f491 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Sep 2021 09:44:34 +0200 Subject: [PATCH 0549/1381] Prepare 3.3 M3 (2021.1.0). See #3771 --- pom.xml | 8 ++++---- src/main/resources/notice.txt | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 7cb1d10f85..e1ecd121e4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.6.0-SNAPSHOT + 2.6.0-M3 @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.6.0-SNAPSHOT + 2.6.0-M3 4.3.2 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-snapshot - https://repo.spring.io/libs-snapshot + spring-libs-milestone + https://repo.spring.io/libs-milestone sonatype-libs-snapshot diff --git a/src/main/resources/notice.txt b/src/main/resources/notice.txt index 29628c3570..ceef18ae5b 100644 --- a/src/main/resources/notice.txt +++ b/src/main/resources/notice.txt @@ -1,4 +1,4 @@ -Spring Data MongoDB 3.3 M2 (2021.1.0) +Spring Data MongoDB 3.3 M3 (2021.1.0) Copyright (c) [2010-2019] Pivotal Software, Inc. This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -27,5 +27,6 @@ conditions of the subcomponent's license, as noted in the LICENSE file. + From 00350edd3265b3d81c1551e7ffb90fa1a72c9fd6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Sep 2021 09:44:56 +0200 Subject: [PATCH 0550/1381] Release version 3.3 M3 (2021.1.0). See #3771 --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index e1ecd121e4..b63985f7c6 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M3 pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 0033bd11d5..ac1428bdf5 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M3 ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index f62c8dc7f4..f3e3c3d92e 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M3 ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 2f73c10eba..6a959b228d 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-SNAPSHOT + 3.3.0-M3 ../pom.xml From 715ae26f3ccb3842f25abdd698295e365aa1b898 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Sep 2021 09:52:18 +0200 Subject: [PATCH 0551/1381] Prepare next development iteration. See #3771 --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index b63985f7c6..e1ecd121e4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M3 + 3.3.0-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index ac1428bdf5..0033bd11d5 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M3 + 3.3.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index f3e3c3d92e..f62c8dc7f4 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M3 + 3.3.0-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 6a959b228d..2f73c10eba 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.3.0-M3 + 3.3.0-SNAPSHOT ../pom.xml From b7ffff47694ba4066eadc8a7359696766b53bc8e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 17 Sep 2021 09:52:21 +0200 Subject: [PATCH 0552/1381] After release cleanups. See #3771 --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index e1ecd121e4..7cb1d10f85 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.data.build spring-data-parent - 2.6.0-M3 + 2.6.0-SNAPSHOT @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.6.0-M3 + 2.6.0-SNAPSHOT 4.3.2 ${mongo} 1.19 @@ -134,8 +134,8 @@ - spring-libs-milestone - https://repo.spring.io/libs-milestone + spring-libs-snapshot + https://repo.spring.io/libs-snapshot sonatype-libs-snapshot From 63d9875576beddd0651c6d7c777f54829dbb6aa1 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 6 Jul 2021 07:54:31 +0200 Subject: [PATCH 0553/1381] Update test for MongoDB Server 5.0. Update assertions for changed return types, add a bit of think time and disable tests for no longer supported features. See #3696 Original pull request: #3753. --- .../config/AbstractIntegrationTests.java | 15 ++++++------- .../core/geo/GeoSpatialIndexTests.java | 8 ++++--- .../core/index/IndexingIntegrationTests.java | 6 ++++- .../DefaultMessageListenerContainerTests.java | 22 ++++++++++++------- .../mongodb/test/util/MongoTestUtils.java | 17 ++++++++++++++ 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 701e2eb986..00a4e9d935 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -21,10 +21,9 @@ import java.util.Set; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; @@ -32,7 +31,7 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.MongoException; import com.mongodb.client.MongoClient; @@ -41,7 +40,7 @@ /** * @author Oliver Gierke */ -@RunWith(SpringRunner.class) +@ExtendWith(SpringExtension.class) @ContextConfiguration public abstract class AbstractIntegrationTests { @@ -71,8 +70,8 @@ protected boolean autoIndexCreation() { @Autowired MongoOperations operations; - @Before - @After + @BeforeEach + @AfterEach public void cleanUp() { for (String collectionName : operations.getCollectionNames()) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java index 449c78f225..10984e0a1c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java @@ -21,8 +21,8 @@ import java.util.List; import java.util.Map; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.geo.Point; @@ -35,6 +35,7 @@ import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import com.mongodb.MongoException; import com.mongodb.WriteConcern; @@ -52,7 +53,7 @@ public class GeoSpatialIndexTests extends AbstractIntegrationTests { @Autowired private MongoTemplate template; - @Before + @BeforeEach public void setUp() { template.setWriteConcern(WriteConcern.JOURNALED); @@ -82,6 +83,7 @@ public void test2dSphereIndex() { } @Test // DATAMONGO-778 + @EnableIfMongoServerVersion(isLessThan = "5.0") public void testHaystackIndex() { try { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 2c61b0fdbf..7c731a37c4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -155,7 +155,11 @@ public void evaluatesTimeoutSpelExpresssionWithBeanReference() { }); assertThat(indexInfo).isPresent(); - assertThat(indexInfo.get()).containsEntry("expireAfterSeconds", 11L); + assertThat(indexInfo.get()).hasEntrySatisfying("expireAfterSeconds", timeout -> { + + // MongoDB 5 returns int not long + assertThat(timeout).isIn(11, 11L); + }); } @Target({ ElementType.FIELD }) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index b973de0cf1..c47918c565 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -38,13 +38,16 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; +import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ErrorHandler; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.changestream.ChangeStreamDocument; @@ -60,9 +63,12 @@ public class DefaultMessageListenerContainerTests { static final String DATABASE_NAME = "change-stream-events"; static final String COLLECTION_NAME = "collection-1"; static final String COLLECTION_2_NAME = "collection-2"; + static final String COLLECTION_3_NAME = "collection-3"; static final Duration TIMEOUT = Duration.ofSeconds(2); + @Client static MongoClient client; + @Template(database = DATABASE_NAME, initialEntitySet = Person.class) // static MongoTemplate template; @@ -74,10 +80,13 @@ public class DefaultMessageListenerContainerTests { private CollectingMessageListener messageListener; @BeforeEach - void beforeEach() { + void beforeEach() throws InterruptedException { + + MongoTestUtils.dropCollectionNow(DATABASE_NAME, COLLECTION_NAME, client); + MongoTestUtils.dropCollectionNow(DATABASE_NAME, COLLECTION_2_NAME, client); + MongoTestUtils.dropCollectionNow(DATABASE_NAME, COLLECTION_3_NAME, client); - template.dropCollection(COLLECTION_NAME); - template.dropCollection(COLLECTION_2_NAME); + Thread.sleep(100); messageListener = new CollectingMessageListener<>(); } @@ -281,7 +290,7 @@ public void abortsSubscriptionOnError() throws InterruptedException { @Test // DATAMONGO-1803 public void callsDefaultErrorHandlerOnError() throws InterruptedException { - dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_3_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -298,10 +307,7 @@ public void callsDefaultErrorHandlerOnError() throws InterruptedException { Document.class); SubscriptionUtils.awaitSubscription(subscription); - - template.dropCollection(COLLECTION_NAME); - - Thread.sleep(20); + dbFactory.getMongoDatabase().drop(); verify(errorHandler, atLeast(1)).handleError(any(DataAccessException.class)); } finally { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 5a41e8a68c..7e29d2a272 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -166,6 +166,23 @@ public static void dropCollectionNow(String dbName, String collectionName, .verifyComplete(); } + /** + * Create a {@link com.mongodb.client.MongoCollection} if it does not exist, or drop and recreate it if it does and + * verify operation result. + * + * @param dbName must not be {@literal null}. + * @param collectionName must not be {@literal null}. + * @param client must not be {@literal null}. + */ + public static void dropCollectionNow(String dbName, String collectionName, + com.mongodb.client.MongoClient client) { + + com.mongodb.client.MongoDatabase database = client.getDatabase(dbName) + .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); + + database.getCollection(collectionName).drop(); + } + /** * Remove all documents from the {@link MongoCollection} with given name in the according {@link MongoDatabase * database}. From 2f208d712ca2353c45529132ba88e3e9b4c339eb Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 6 Jul 2021 09:28:32 +0200 Subject: [PATCH 0554/1381] Update CI to cover MongoDB Server 5.0. MongoDB has alpha releases in a slightly different location on their distribution server. And they use different keys for signing these alpha releases compared to the overall package listing. Closes #3696 Original pull request: #3753. --- Jenkinsfile | 40 ++++++++++++++++++++++++++++++ ci/openjdk8-mongodb-5.0/Dockerfile | 17 +++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 ci/openjdk8-mongodb-5.0/Dockerfile diff --git a/Jenkinsfile b/Jenkinsfile index 1eb84755a5..1ee5ed5c5f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -14,6 +14,22 @@ pipeline { stages { stage("Docker images") { parallel { + stage('Publish JDK 8 + MongoDB 5.0') { + when { + changeset "ci/openjdk8-mongodb-5.0/**" + } + agent { label 'data' } + options { timeout(time: 30, unit: 'MINUTES') } + + steps { + script { + def image = docker.build("springci/spring-data-openjdk8-with-mongodb-5.0.0", "ci/openjdk8-mongodb-5.0/") + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + image.push() + } + } + } + } stage('Publish JDK 8 + MongoDB 4.0') { when { changeset "ci/openjdk8-mongodb-4.0/**" @@ -151,6 +167,30 @@ pipeline { } } + stage("test: mongodb 5.0 (jdk8)") { + agent { + label 'data' + } + options { timeout(time: 30, unit: 'MINUTES') } + environment { + ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c') + } + steps { + script { + docker.withRegistry('', 'hub.docker.com-springbuildmaster') { + docker.image('springci/spring-data-openjdk8-with-mongodb-5.0.0:latest').inside('-v $HOME:/tmp/jenkins-home') { + sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log' + sh 'mongod --setParameter transactionLifetimeLimitSeconds=90 --setParameter maxTransactionLockRequestTimeoutMillis=10000 --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &' + sh 'sleep 10' + sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"' + sh 'sleep 15' + sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml clean dependency:list test -Duser.name=jenkins -Dsort -U -B' + } + } + } + } + } + stage("test: baseline (jdk16)") { agent { label 'data' diff --git a/ci/openjdk8-mongodb-5.0/Dockerfile b/ci/openjdk8-mongodb-5.0/Dockerfile new file mode 100644 index 0000000000..658b615bbd --- /dev/null +++ b/ci/openjdk8-mongodb-5.0/Dockerfile @@ -0,0 +1,17 @@ +FROM adoptopenjdk/openjdk8:latest + +ENV TZ=Etc/UTC +ENV DEBIAN_FRONTEND=noninteractive + +RUN set -eux; \ + apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 wget ; \ + # MongoDB 5.0 release signing key + apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv B00A0BD1E2C63C11 ; \ + # Needed when MongoDB creates a 5.0 folder. + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list; \ + echo ${TZ} > /etc/timezone; + +RUN apt-get update; \ + apt-get install -y mongodb-org=5.0.0 mongodb-org-server=5.0.0 mongodb-org-shell=5.0.0 mongodb-org-mongos=5.0.0 mongodb-org-tools=5.0.0; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/*; From 7f585382925f4a40153221e4039268cf4be40c97 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 21 Sep 2021 15:16:12 +0200 Subject: [PATCH 0555/1381] Use HTTPS in Dockerfiles for package download. See #3696 Original pull request: #3753. --- ci/openjdk11-mongodb-4.4/Dockerfile | 3 +++ ci/openjdk16-mongodb-4.4/Dockerfile | 5 ++++- ci/openjdk8-mongodb-4.0/Dockerfile | 3 +++ ci/openjdk8-mongodb-4.4/Dockerfile | 3 +++ ci/openjdk8-mongodb-5.0/Dockerfile | 5 ++++- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ci/openjdk11-mongodb-4.4/Dockerfile b/ci/openjdk11-mongodb-4.4/Dockerfile index 6c94ac38ff..7de227c4d9 100644 --- a/ci/openjdk11-mongodb-4.4/Dockerfile +++ b/ci/openjdk11-mongodb-4.4/Dockerfile @@ -4,6 +4,9 @@ ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive RUN set -eux; \ + sed -i -e 's/archive.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/security.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/http/https/g' /etc/apt/sources.list ; \ apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 656408E390CFB1F5 ; \ echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list; \ diff --git a/ci/openjdk16-mongodb-4.4/Dockerfile b/ci/openjdk16-mongodb-4.4/Dockerfile index 7a1e47cf00..5f49272c4a 100644 --- a/ci/openjdk16-mongodb-4.4/Dockerfile +++ b/ci/openjdk16-mongodb-4.4/Dockerfile @@ -1,9 +1,12 @@ -FROM adoptopenjdk/openjdk16:latest +FROM adoptopenjdk/openjdk16:latest ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive RUN set -eux; \ + sed -i -e 's/archive.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/security.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/http/https/g' /etc/apt/sources.list ; \ apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 656408E390CFB1F5 ; \ echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list; \ diff --git a/ci/openjdk8-mongodb-4.0/Dockerfile b/ci/openjdk8-mongodb-4.0/Dockerfile index e05068ab32..bb75ccfc14 100644 --- a/ci/openjdk8-mongodb-4.0/Dockerfile +++ b/ci/openjdk8-mongodb-4.0/Dockerfile @@ -4,6 +4,9 @@ ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive RUN RUN set -eux; \ + sed -i -e 's/archive.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/security.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/http/https/g' /etc/apt/sources.list ; \ apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 ; \ echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.0.list; \ diff --git a/ci/openjdk8-mongodb-4.4/Dockerfile b/ci/openjdk8-mongodb-4.4/Dockerfile index 79774dd269..f9a814533b 100644 --- a/ci/openjdk8-mongodb-4.4/Dockerfile +++ b/ci/openjdk8-mongodb-4.4/Dockerfile @@ -4,6 +4,9 @@ ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive RUN set -eux; \ + sed -i -e 's/archive.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/security.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/http/https/g' /etc/apt/sources.list ; \ apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 ; \ apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 656408E390CFB1F5 ; \ echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list; \ diff --git a/ci/openjdk8-mongodb-5.0/Dockerfile b/ci/openjdk8-mongodb-5.0/Dockerfile index 658b615bbd..53509efd05 100644 --- a/ci/openjdk8-mongodb-5.0/Dockerfile +++ b/ci/openjdk8-mongodb-5.0/Dockerfile @@ -4,6 +4,9 @@ ENV TZ=Etc/UTC ENV DEBIAN_FRONTEND=noninteractive RUN set -eux; \ + sed -i -e 's/archive.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/security.ubuntu.com/mirror.one.com/g' /etc/apt/sources.list; \ + sed -i -e 's/http/https/g' /etc/apt/sources.list ; \ apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2 wget ; \ # MongoDB 5.0 release signing key apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv B00A0BD1E2C63C11 ; \ @@ -12,6 +15,6 @@ RUN set -eux; \ echo ${TZ} > /etc/timezone; RUN apt-get update; \ - apt-get install -y mongodb-org=5.0.0 mongodb-org-server=5.0.0 mongodb-org-shell=5.0.0 mongodb-org-mongos=5.0.0 mongodb-org-tools=5.0.0; \ + apt-get install -y mongodb-org=5.0.3 mongodb-org-server=5.0.3 mongodb-org-shell=5.0.3 mongodb-org-mongos=5.0.3 mongodb-org-tools=5.0.3; \ apt-get clean; \ rm -rf /var/lib/apt/lists/*; From 9e2f6055a3917b8f9927859f28b389765eb2bd68 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 6 Jul 2021 10:40:10 +0200 Subject: [PATCH 0556/1381] Refine CI job triggers. See #3696 Original pull request: #3753. --- Jenkinsfile | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1ee5ed5c5f..a7e2d38bb9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -83,8 +83,9 @@ pipeline { stage("test: baseline (jdk8)") { when { + beforeAgent(true) anyOf { - branch 'main' + branch(pattern: "main|(\\d\\.\\d\\.x)", comparator: "REGEXP") not { triggeredBy 'UpstreamCause' } } } @@ -113,8 +114,9 @@ pipeline { stage("Test other configurations") { when { + beforeAgent(true) allOf { - branch 'main' + branch(pattern: "main|(\\d\\.\\d\\.x)", comparator: "REGEXP") not { triggeredBy 'UpstreamCause' } } } @@ -219,8 +221,9 @@ pipeline { stage('Release to artifactory') { when { + beforeAgent(true) anyOf { - branch 'main' + branch(pattern: "main|(\\d\\.\\d\\.x)", comparator: "REGEXP") not { triggeredBy 'UpstreamCause' } } } @@ -250,35 +253,6 @@ pipeline { } } } - - stage('Publish documentation') { - when { - branch 'main' - } - agent { - label 'data' - } - options { timeout(time: 20, unit: 'MINUTES') } - - environment { - ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c') - } - - steps { - script { - docker.withRegistry('', 'hub.docker.com-springbuildmaster') { - docker.image('adoptopenjdk/openjdk8:latest').inside('-v $HOME:/tmp/jenkins-home') { - sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -s settings.xml -Pci,distribute ' + - '-Dartifactory.server=https://repo.spring.io ' + - "-Dartifactory.username=${ARTIFACTORY_USR} " + - "-Dartifactory.password=${ARTIFACTORY_PSW} " + - "-Dartifactory.distribution-repository=temp-private-local " + - '-Dmaven.test.skip=true clean deploy -U -B' - } - } - } - } - } } post { From 2f98a6656bb17b5f909a39d4bf5df8554864ce28 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 24 Sep 2021 10:35:38 +0200 Subject: [PATCH 0557/1381] Fix javadoc errors and warnings Closes: #3835 --- .../data/mongodb/BindableMongoExpression.java | 2 +- .../data/mongodb/MongoCollectionUtils.java | 4 +- .../data/mongodb/MongoDatabaseUtils.java | 10 +- .../data/mongodb/MongoExpression.java | 2 +- .../data/mongodb/MongoResourceHolder.java | 2 +- .../data/mongodb/MongoTransactionManager.java | 16 +- .../mongodb/ReactiveMongoDatabaseUtils.java | 10 +- .../mongodb/ReactiveMongoResourceHolder.java | 2 +- .../ReactiveMongoTransactionManager.java | 12 +- .../SessionAwareMethodInterceptor.java | 2 +- .../data/mongodb/SpringDataMongoDB.java | 2 +- .../config/MongoConfigurationSupport.java | 3 +- .../mongodb/core/ChangeStreamOptions.java | 4 +- .../data/mongodb/core/CollectionOptions.java | 2 +- .../mongodb/core/ExecutableFindOperation.java | 2 +- .../core/ExecutableUpdateOperation.java | 2 +- .../mongodb/core/FindAndReplaceOptions.java | 2 +- .../core/MongoDatabaseFactorySupport.java | 2 +- .../mongodb/core/MongoDbFactorySupport.java | 2 +- .../mongodb/core/MongoJsonSchemaCreator.java | 3 +- .../data/mongodb/core/MongoOperations.java | 129 +++++++------ .../data/mongodb/core/MongoTemplate.java | 6 +- .../core/ReactiveChangeStreamOperation.java | 2 +- .../mongodb/core/ReactiveFindOperation.java | 6 +- .../mongodb/core/ReactiveMongoOperations.java | 181 +++++++++--------- .../mongodb/core/ReactiveMongoTemplate.java | 6 +- .../mongodb/core/ReactiveSessionCallback.java | 2 +- .../mongodb/core/ReactiveSessionScoped.java | 4 +- .../data/mongodb/core/ScriptOperations.java | 6 +- .../data/mongodb/core/SessionCallback.java | 2 +- .../data/mongodb/core/SessionScoped.java | 6 +- .../mongodb/core/aggregation/Aggregation.java | 4 +- .../AggregationSpELExpression.java | 4 +- .../core/aggregation/AggregationUpdate.java | 3 +- .../core/aggregation/ArithmeticOperators.java | 34 ++-- .../core/aggregation/BucketAutoOperation.java | 6 +- .../core/aggregation/BucketOperation.java | 3 +- .../core/aggregation/ConvertOperators.java | 4 +- .../core/aggregation/CountOperation.java | 3 +- .../core/aggregation/DateOperators.java | 6 +- .../aggregation/GraphLookupOperation.java | 3 +- .../core/aggregation/GroupOperation.java | 2 +- ...DelegatingAggregationOperationContext.java | 2 +- .../core/aggregation/RedactOperation.java | 3 +- .../core/aggregation/ScriptOperators.java | 36 ++-- .../aggregation/SetWindowFieldsOperation.java | 3 +- .../aggregation/SortByCountOperation.java | 7 +- .../core/aggregation/UnionWithOperation.java | 2 +- .../core/convert/MappingMongoConverter.java | 2 +- .../mongodb/core/convert/QueryMapper.java | 2 +- .../data/mongodb/core/geo/GeoJsonModule.java | 2 +- .../mongodb/core/index/CompoundIndex.java | 2 +- .../mongodb/core/index/DurationStyle.java | 2 +- .../data/mongodb/core/index/HashIndexed.java | 2 +- .../mongodb/core/index/WildcardIndex.java | 4 +- .../data/mongodb/core/mapping/Encrypted.java | 4 +- .../data/mongodb/core/mapping/Field.java | 2 +- .../data/mongodb/core/mapping/FieldType.java | 2 +- .../data/mongodb/core/mapping/ShardKey.java | 2 +- .../data/mongodb/core/mapping/Sharded.java | 6 +- .../data/mongodb/core/mapping/TimeSeries.java | 3 +- .../data/mongodb/core/mapping/Unwrapped.java | 4 +- .../core/mapping/event/AfterDeleteEvent.java | 2 +- .../core/messaging/ChangeStreamRequest.java | 14 +- .../DefaultMessageListenerContainer.java | 2 +- .../messaging/MessageListenerContainer.java | 24 +-- .../mongodb/core/messaging/Subscription.java | 4 +- .../core/messaging/TailableCursorRequest.java | 6 +- .../data/mongodb/core/query/Collation.java | 2 +- .../data/mongodb/core/query/Criteria.java | 4 +- .../data/mongodb/core/query/NearQuery.java | 2 +- .../mongodb/core/schema/JsonSchemaObject.java | 2 +- .../mongodb/core/script/NamedMongoScript.java | 4 +- .../data/mongodb/repository/Aggregation.java | 26 +-- .../data/mongodb/repository/Query.java | 12 +- .../repository/query/MongoQueryCreator.java | 2 +- 76 files changed, 346 insertions(+), 360 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BindableMongoExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BindableMongoExpression.java index 982f683d53..ac735be37f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BindableMongoExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BindableMongoExpression.java @@ -31,7 +31,7 @@ * expression. The expression will be wrapped within { ... } if necessary. The actual parsing and parameter * binding of placeholders like {@code ?0} is delayed upon first call on the the target {@link Document} via * {@link #toDocument()}. - *

      + *
      * *

        * $toUpper : $name                -> { '$toUpper' : '$name' }
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java
      index 3d85a33dcb..1b796eabd2 100644
      --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java
      +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoCollectionUtils.java
      @@ -20,8 +20,8 @@
       
       /**
        * Helper class featuring helper methods for working with MongoDb collections.
      - * 

      - *

      + *
      + *
      * Mainly intended for internal use within the framework. * * @author Thomas Risberg diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index c9342ec4f6..f0b6c2228a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -30,7 +30,7 @@ * Helper class for managing a {@link MongoDatabase} instances via {@link MongoDatabaseFactory}. Used for obtaining * {@link ClientSession session bound} resources, such as {@link MongoDatabase} and * {@link com.mongodb.client.MongoCollection} suitable for transactional usage. - *

      + *
      * Note: Intended for internal usage only. * * @author Christoph Strobl @@ -43,7 +43,7 @@ public class MongoDatabaseUtils { /** * Obtain the default {@link MongoDatabase database} form the given {@link MongoDatabaseFactory factory} using * {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * @@ -56,7 +56,7 @@ public static MongoDatabase getDatabase(MongoDatabaseFactory factory) { /** * Obtain the default {@link MongoDatabase database} form the given {@link MongoDatabaseFactory factory}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * @@ -71,7 +71,7 @@ public static MongoDatabase getDatabase(MongoDatabaseFactory factory, SessionSyn /** * Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDatabaseFactory factory} using * {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * @@ -85,7 +85,7 @@ public static MongoDatabase getDatabase(@Nullable String dbName, MongoDatabaseFa /** * Obtain the {@link MongoDatabase database} with given name form the given {@link MongoDatabaseFactory factory}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current * {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoExpression.java index 541118b114..2ea38af67f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoExpression.java @@ -18,7 +18,7 @@ /** * Wrapper object for MongoDB expressions like {@code $toUpper : $name} that manifest as {@link org.bson.Document} when * passed on to the driver. - *

      + *
      * A set of predefined {@link MongoExpression expressions}, including a * {@link org.springframework.data.mongodb.core.aggregation.AggregationSpELExpression SpEL based variant} for method * like expressions (eg. {@code toUpper(name)}) are available via the diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java index 90a3b32023..157489e11c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoResourceHolder.java @@ -24,7 +24,7 @@ /** * MongoDB specific {@link ResourceHolderSupport resource holder}, wrapping a {@link ClientSession}. * {@link MongoTransactionManager} binds instances of this class to the thread. - *

      + *
      * Note: Intended for internal usage only. * * @author Christoph Strobl diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java index 1e6013d73d..d244da6296 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java @@ -37,18 +37,18 @@ /** * A {@link org.springframework.transaction.PlatformTransactionManager} implementation that manages * {@link ClientSession} based transactions for a single {@link MongoDatabaseFactory}. - *

      + *
      * Binds a {@link ClientSession} from the specified {@link MongoDatabaseFactory} to the thread. - *

      + *
      * {@link TransactionDefinition#isReadOnly() Readonly} transactions operate on a {@link ClientSession} and enable causal * consistency, and also {@link ClientSession#startTransaction() start}, {@link ClientSession#commitTransaction() * commit} or {@link ClientSession#abortTransaction() abort} a transaction. - *

      + *
      * Application code is required to retrieve the {@link com.mongodb.client.MongoDatabase} via * {@link MongoDatabaseUtils#getDatabase(MongoDatabaseFactory)} instead of a standard * {@link MongoDatabaseFactory#getMongoDatabase()} call. Spring classes such as * {@link org.springframework.data.mongodb.core.MongoTemplate} use this strategy implicitly. - *

      + *
      * By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. One may override * {@link #doCommit(MongoTransactionObject)} to implement the * Retry Commit Operation @@ -69,11 +69,11 @@ public class MongoTransactionManager extends AbstractPlatformTransactionManager /** * Create a new {@link MongoTransactionManager} for bean-style usage. - *

      + *
      * Note:The {@link MongoDatabaseFactory db factory} has to be * {@link #setDbFactory(MongoDatabaseFactory) set} before using the instance. Use this constructor to prepare a * {@link MongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}. - *

      + *
      * Optionally it is possible to set default {@link TransactionOptions transaction options} defining * {@link com.mongodb.ReadConcern} and {@link com.mongodb.WriteConcern}. * @@ -212,8 +212,8 @@ protected final void doCommit(DefaultTransactionStatus status) throws Transactio * By default those labels are ignored, nevertheless one might check for * {@link MongoException#UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL transient commit errors labels} and retry the the * commit.
      + *

       	 * 
      -	 *     
       	 * int retries = 3;
       	 * do {
       	 *     try {
      @@ -226,8 +226,8 @@ protected final void doCommit(DefaultTransactionStatus status) throws Transactio
       	 *     }
       	 *     Thread.sleep(500);
       	 * } while (--retries > 0);
      -	 *     
      *
      + *
      * * @param transactionObject never {@literal null}. * @throws Exception in case of transaction errors. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java index 4699ac56c2..4ae9e227f1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseUtils.java @@ -36,7 +36,7 @@ * Helper class for managing reactive {@link MongoDatabase} instances via {@link ReactiveMongoDatabaseFactory}. Used for * obtaining {@link ClientSession session bound} resources, such as {@link MongoDatabase} and {@link MongoCollection} * suitable for transactional usage. - *

      + *
      * Note: Intended for internal usage only. * * @author Mark Paluch @@ -75,7 +75,7 @@ public static Mono isTransactionActive(ReactiveMongoDatabaseFactory dat /** * Obtain the default {@link MongoDatabase database} form the given {@link ReactiveMongoDatabaseFactory factory} using * {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber * {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * @@ -88,7 +88,7 @@ public static Mono getDatabase(ReactiveMongoDatabaseFactory facto /** * Obtain the default {@link MongoDatabase database} form the given {@link ReactiveMongoDatabaseFactory factory}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber * {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * @@ -104,7 +104,7 @@ public static Mono getDatabase(ReactiveMongoDatabaseFactory facto /** * Obtain the {@link MongoDatabase database} with given name form the given {@link ReactiveMongoDatabaseFactory * factory} using {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber * {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * @@ -119,7 +119,7 @@ public static Mono getDatabase(String dbName, ReactiveMongoDataba /** * Obtain the {@link MongoDatabase database} with given name form the given {@link ReactiveMongoDatabaseFactory * factory}. - *

      + *
      * Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber * {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java index b1f1c06d08..b3338fd7ba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoResourceHolder.java @@ -24,7 +24,7 @@ /** * MongoDB specific resource holder, wrapping a {@link ClientSession}. {@link ReactiveMongoTransactionManager} binds * instances of this class to the subscriber context. - *

      + *
      * Note: Intended for internal usage only. * * @author Mark Paluch diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java index 63706eff8a..711af76f53 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoTransactionManager.java @@ -38,21 +38,21 @@ * A {@link org.springframework.transaction.ReactiveTransactionManager} implementation that manages * {@link com.mongodb.reactivestreams.client.ClientSession} based transactions for a single * {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory}. - *

      + *
      * Binds a {@link ClientSession} from the specified * {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory} to the subscriber * {@link reactor.util.context.Context}. - *

      + *
      * {@link org.springframework.transaction.TransactionDefinition#isReadOnly() Readonly} transactions operate on a * {@link ClientSession} and enable causal consistency, and also {@link ClientSession#startTransaction() start}, * {@link com.mongodb.reactivestreams.client.ClientSession#commitTransaction() commit} or * {@link ClientSession#abortTransaction() abort} a transaction. - *

      + *
      * Application code is required to retrieve the {@link com.mongodb.reactivestreams.client.MongoDatabase} via * {@link org.springframework.data.mongodb.ReactiveMongoDatabaseUtils#getDatabase(ReactiveMongoDatabaseFactory)} instead * of a standard {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getMongoDatabase()} call. Spring * classes such as {@link org.springframework.data.mongodb.core.ReactiveMongoTemplate} use this strategy implicitly. - *

      + *
      * By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. You can override * {@link #doCommit(TransactionSynchronizationManager, ReactiveMongoTransactionObject)} to implement the * Retry Commit Operation @@ -71,11 +71,11 @@ public class ReactiveMongoTransactionManager extends AbstractReactiveTransaction /** * Create a new {@link ReactiveMongoTransactionManager} for bean-style usage. - *

      + *
      * Note:The {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory db factory} has to * be {@link #setDatabaseFactory(ReactiveMongoDatabaseFactory)} set} before using the instance. Use this constructor * to prepare a {@link ReactiveMongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}. - *

      + *
      * Optionally it is possible to set default {@link TransactionOptions transaction options} defining * {@link com.mongodb.ReadConcern} and {@link com.mongodb.WriteConcern}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java index da48f22154..b9b2c88130 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SessionAwareMethodInterceptor.java @@ -35,7 +35,7 @@ /** * {@link MethodInterceptor} implementation looking up and invoking an alternative target method having * {@link ClientSession} as its first argument. This allows seamless integration with the existing code base. - *

      + *
      * The {@link MethodInterceptor} is aware of methods on {@code MongoCollection} that my return new instances of itself * like (eg. {@link com.mongodb.reactivestreams.client.MongoCollection#withWriteConcern(WriteConcern)} and decorate them * if not already proxied. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java index dbbf146fc1..808b576bcb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/SpringDataMongoDB.java @@ -48,7 +48,7 @@ public static MongoDriverInformation driverInformation() { /** * Fetches the "Implementation-Version" manifest attribute from the jar file. - *

      + *
      * Note that some ClassLoaders do not expose the package metadata, hence this class might not be able to determine the * version in all environments. In this case the current Major version is returned as a fallback. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java index 52ec72d171..5fe0c4fe4e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java @@ -172,8 +172,7 @@ protected Set> scanForEntities(String basePackage) throws ClassNotFound /** * Configures whether to abbreviate field names for domain objects by configuring a - * {@link CamelCaseAbbreviatingFieldNamingStrategy} on the {@link MongoMappingContext} instance created. For advanced - * customization needs, consider overriding {@link #mappingMongoConverter()}. + * {@link CamelCaseAbbreviatingFieldNamingStrategy} on the {@link MongoMappingContext} instance created. * * @return */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java index a4f6f7e226..3fe6767533 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamOptions.java @@ -242,13 +242,13 @@ public ChangeStreamOptionsBuilder collation(Collation collation) { /** * Set the filter to apply. - *

      + *
      * Fields on aggregation expression root level are prefixed to map to fields contained in * {@link ChangeStreamDocument#getFullDocument() fullDocument}. However {@literal operationType}, {@literal ns}, * {@literal documentKey} and {@literal fullDocument} are reserved words that will be omitted, and therefore taken * as given, during the mapping procedure. You may want to have a look at the * structure of Change Events. - *

      + *
      * Use {@link org.springframework.data.mongodb.core.aggregation.TypedAggregation} to ensure filter expressions are * mapped to domain type fields. * 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 edff52bb74..f866896694 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 @@ -428,7 +428,7 @@ public Optional getValidationLevel() { /** * Get the {@code validationAction} to perform. * - * @return @return {@link Optional#empty()} if not set. + * @return {@link Optional#empty()} if not set. */ public Optional getValidationAction() { return Optional.ofNullable(validationAction); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index d67212bdc6..f41af5c6c5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -125,7 +125,7 @@ default Optional first() { /** * Get the number of matching elements. - *

      + *
      * This method uses an {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) aggregation * execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees shard, * session and transaction compliance. In case an inaccurate count satisfies the applications needs use diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index a8b58669e3..32b7017e41 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -89,7 +89,7 @@ default Optional findAndModify() { /** * Trigger - * findOneAndReplace + * findOneAndReplace * execution by calling one of the terminating methods. * * @author Mark Paluch diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java index 6122837a27..42a8a3ef77 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/FindAndReplaceOptions.java @@ -17,7 +17,7 @@ /** * Options for - * findOneAndReplace. + * findOneAndReplace. *
      * Defaults to *

      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java index dac4b0d6d7..9c8419a154 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java @@ -33,7 +33,7 @@ /** * Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as * database name and exception translator. - *

      + *
      * Not intended to be used directly. * * @author Christoph Strobl diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index bc0e39bbc9..ba530d502f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -20,7 +20,7 @@ /** * Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as * database name and exception translator. - *

      + *
      * Not intended to be used directly. * * @author Christoph Strobl diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java index 5e5bc50644..f5b620d0fb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoJsonSchemaCreator.java @@ -40,6 +40,7 @@ * following mapping rules. *

      * Required Properties + *

      *
        *
      • Properties of primitive type
      • *
      @@ -61,7 +62,7 @@ * {@link org.springframework.data.annotation.Id _id} properties using types that can be converted into * {@link org.bson.types.ObjectId} like {@link String} will be mapped to {@code type : 'object'} unless there is more * specific information available via the {@link org.springframework.data.mongodb.core.mapping.MongoId} annotation. - *

      + * {@link Encrypted} properties will contain {@literal encrypt} information. * * @author Christoph Strobl diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index e4a4b0868f..c015fb5a49 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -58,7 +58,7 @@ * Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but * a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be the target of a JDK * proxy). - *

      + *
      * NOTE: Some operations cannot be executed within a MongoDB transaction. Please refer to the MongoDB * specific documentation to learn more about Multi * Document Transactions. @@ -125,7 +125,7 @@ public interface MongoOperations extends FluentMongoOperations { /** * Executes a {@link DbCallback} translating any exceptions as necessary. - *

      + *
      * Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param action callback object that specifies the MongoDB actions to perform on the passed in DB instance. Must not @@ -138,7 +138,7 @@ public interface MongoOperations extends FluentMongoOperations { /** * Executes the given {@link CollectionCallback} on the entity collection of the specified class. - *

      + *
      * Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param entityClass class that determines the collection to use. Must not be {@literal null}. @@ -151,7 +151,7 @@ public interface MongoOperations extends FluentMongoOperations { /** * Executes the given {@link CollectionCallback} on the collection of the given name. - *

      + *
      * Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param collectionName the name of the collection that specifies which {@link MongoCollection} instance will be @@ -176,7 +176,7 @@ public interface MongoOperations extends FluentMongoOperations { /** * Obtain a {@link ClientSession session} bound instance of {@link SessionScoped} binding the {@link ClientSession} * provided by the given {@link Supplier} to each and every command issued against MongoDB. - *

      + *
      * Note: It is up to the caller to manage the {@link ClientSession} lifecycle. Use the * {@link SessionScoped#execute(SessionCallback, Consumer)} hook to potentially close the {@link ClientSession}. * @@ -212,7 +212,7 @@ public T execute(SessionCallback action, Consumer onComple /** * Obtain a {@link ClientSession} bound instance of {@link MongoOperations}. - *

      + *
      * Note: It is up to the caller to manage the {@link ClientSession} lifecycle. * * @param session must not be {@literal null}. @@ -300,7 +300,7 @@ public T execute(SessionCallback action, Consumer onComple * is created on first interaction with the server. Collections can be explicitly created via * {@link #createCollection(Class)}. Please make sure to check if the collection {@link #collectionExists(Class) * exists} first. - *

      + *
      * Translate any exceptions as necessary. * * @param collectionName name of the collection. Must not be {@literal null}. @@ -310,7 +310,7 @@ public T execute(SessionCallback action, Consumer onComple /** * Check to see if a collection with a name indicated by the entity class exists. - *

      + *
      * Translate any exceptions as necessary. * * @param entityClass class that determines the name of the collection. Must not be {@literal null}. @@ -320,7 +320,7 @@ public T execute(SessionCallback action, Consumer onComple /** * Check to see if a collection with a given name exists. - *

      + *
      * Translate any exceptions as necessary. * * @param collectionName name of the collection. Must not be {@literal null}. @@ -330,7 +330,7 @@ public T execute(SessionCallback action, Consumer onComple /** * Drop the collection with the name indicated by the entity class. - *

      + *
      * Translate any exceptions as necessary. * * @param entityClass class that determines the collection to drop/delete. Must not be {@literal null}. @@ -339,7 +339,7 @@ public T execute(SessionCallback action, Consumer onComple /** * Drop the collection with the given name. - *

      + *
      * Translate any exceptions as necessary. * * @param collectionName name of the collection to drop/delete. @@ -403,10 +403,10 @@ public T execute(SessionCallback action, Consumer onComple /** * Query for a list of objects of type T from the collection used by the entity class. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way * to map objects since the test for class type is done in the client and not on the server. * @@ -417,10 +417,10 @@ public T execute(SessionCallback action, Consumer onComple /** * Query for a list of objects of type T from the specified collection. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way * to map objects since the test for class type is done in the client and not on the server. * @@ -539,11 +539,11 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN /** * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. - *

      + *
      * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that * needs to be closed. The raw results will be mapped to the given entity class and are returned as stream. The name * of the inputCollection is derived from the inputType of the aggregation. - *

      + *
      * Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. * @@ -557,10 +557,10 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN /** * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. - *

      + *
      * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that * needs to be closed. The raw results will be mapped to the given entity class. - *

      + *
      * Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. * @@ -576,10 +576,10 @@ GroupByResults group(@Nullable Criteria criteria, String inputCollectionN /** * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. - *

      + *
      * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that * needs to be closed. The raw results will be mapped to the given entity class. - *

      + *
      * Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. * @@ -702,10 +702,10 @@ MapReduceResults mapReduce(Query query, String inputCollectionName, Strin /** * Map the results of an ad-hoc query on the collection for the entity class to a single instance of an object of the * specified type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -720,10 +720,10 @@ MapReduceResults mapReduce(Query query, String inputCollectionName, Strin /** * Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified * type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -768,10 +768,10 @@ MapReduceResults mapReduce(Query query, String inputCollectionName, Strin /** * Map the results of an ad-hoc query on the collection for the entity class to a List of the specified type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -784,10 +784,10 @@ MapReduceResults mapReduce(Query query, String inputCollectionName, Strin /** * Map the results of an ad-hoc query on the specified collection to a List of the specified type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -881,7 +881,7 @@ default List findDistinct(Query query, String field, String collection, C } /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. * * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional @@ -897,7 +897,7 @@ default List findDistinct(Query query, String field, String collection, C T findAndModify(Query query, UpdateDefinition update, Class entityClass); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. * * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional @@ -914,7 +914,7 @@ default List findDistinct(Query query, String field, String collection, C T findAndModify(Query query, UpdateDefinition update, Class entityClass, String collectionName); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking * {@link FindAndModifyOptions} into account. * @@ -934,7 +934,7 @@ default List findDistinct(Query query, String field, String collection, C T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class entityClass); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking * {@link FindAndModifyOptions} into account. * @@ -957,7 +957,7 @@ T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions o /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} * document.
      * The collection name is derived from the {@literal replacement} type.
      @@ -977,7 +977,7 @@ default T findAndReplace(Query query, T replacement) { /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} * document.
      * Options are defaulted to {@link FindAndReplaceOptions#empty()}.
      @@ -997,7 +997,7 @@ default T findAndReplace(Query query, T replacement, String collectionName) /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -1018,7 +1018,7 @@ default T findAndReplace(Query query, T replacement, FindAndReplaceOptions o /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -1041,7 +1041,7 @@ default T findAndReplace(Query query, T replacement, FindAndReplaceOptions o /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -1066,7 +1066,7 @@ default T findAndReplace(Query query, T replacement, FindAndReplaceOptions o /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -1094,7 +1094,7 @@ default T findAndReplace(Query query, S replacement, FindAndReplaceOption /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -1120,9 +1120,9 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * Map the results of an ad-hoc query on the collection for the entity type to a single instance of an object of the * specified type. The first document that matches the query is returned and also removed from the collection in the * database. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -1137,10 +1137,10 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option /** * Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified * type. The first document that matches the query is returned and also removed from the collection in the database. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -1160,7 +1160,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. - *

      + *
      * This method uses an * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees @@ -1182,7 +1182,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. - *

      + *
      * This method uses an * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees @@ -1199,7 +1199,7 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option /** * Estimate the number of documents, in the collection {@link #getCollectionName(Class) identified by the given type}, * based on collection statistics. - *

      + *
      * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside * transactions. * @@ -1215,7 +1215,7 @@ default long estimatedCount(Class entityClass) { /** * Estimate the number of documents in the given collection based on collection statistics. - *

      + *
      * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside * transactions. * @@ -1232,7 +1232,7 @@ default long estimatedCount(Class entityClass) { * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. - *

      + *
      * This method uses an * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees @@ -1249,17 +1249,17 @@ default long estimatedCount(Class entityClass) { /** * Insert the object into the collection for the entity type of the object to save. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See * Spring's * Type Conversion" for more details. - *

      + *
      * Insert is used to initially store the object into the database. To update an existing object use the save method. - *

      + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1270,12 +1270,12 @@ default long estimatedCount(Class entityClass) { /** * Insert the object into the specified collection. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * Insert is used to initially store the object into the database. To update an existing object use the save method. - *

      + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1315,16 +1315,16 @@ default long estimatedCount(Class entityClass) { /** * Save the object to the collection for the entity type of the object to save. This will perform an insert if the * object is not already present, that is an 'upsert'. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See * Spring's * Type Conversion" for more details. - *

      + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1336,16 +1336,15 @@ default long estimatedCount(Class entityClass) { /** * Save the object to the specified collection. This will perform an insert if the object is not already present, that * is an 'upsert'. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your - * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See Spring's Type - * Conversion" for more details. - *

      + * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. + * See Spring's Type Conversion for more details. + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. 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 fb0780c5c8..b3fb915687 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 @@ -338,7 +338,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws /** * Set the {@link EntityCallbacks} instance to use when invoking * {@link org.springframework.data.mapping.callback.EntityCallback callbacks} like the {@link BeforeSaveCallback}. - *

      + *
      * Overrides potentially existing {@link EntityCallbacks}. * * @param entityCallbacks must not be {@literal null}. @@ -2664,7 +2664,7 @@ Document getMappedValidator(Validator validator, Class domainType) { /** * Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter. * The first document that matches the query is returned and also removed from the collection in the database. - *

      + *
      * The query document is specified as a standard Document and so is the fields specification. * * @param collectionName name of the collection to retrieve the objects from @@ -3493,7 +3493,7 @@ public MongoDatabaseFactory getMongoDatabaseFactory() { /** * {@link MongoTemplate} extension bound to a specific {@link ClientSession} that is applied when interacting with the * server through the driver API. - *

      + *
      * The prepare steps for {@link MongoDatabase} and {@link MongoCollection} proxy the target and invoke the desired * target method matching the actual arguments plus a {@link ClientSession}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java index 279f4184fb..d834af4b32 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveChangeStreamOperation.java @@ -71,7 +71,7 @@ interface TerminatingChangeStream { /** * Start listening to changes. The stream will not be completed unless the {@link org.reactivestreams.Subscription} * is {@link org.reactivestreams.Subscription#cancel() canceled}. - *

      + *
      * However, the stream may become dead, or invalid, if all watched collections, databases are dropped. */ Flux> listen(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index 9a65090922..b06623197d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -91,10 +91,10 @@ interface TerminatingFind { * Get all matching elements using a {@link com.mongodb.CursorType#TailableAwait tailable cursor}. The stream will * not be completed unless the {@link org.reactivestreams.Subscription} is * {@link org.reactivestreams.Subscription#cancel() canceled}. - *

      + *
      * However, the stream may become dead, or invalid, if either the query returns no match or the cursor returns the * document at the "end" of the collection and then the application deletes that document. - *

      + *
      * A stream that is no longer in use must be {@link reactor.core.Disposable#dispose()} disposed} otherwise the * streams will linger and exhaust resources.
      * NOTE: Requires a capped collection. @@ -106,7 +106,7 @@ interface TerminatingFind { /** * Get the number of matching elements. - *

      + *
      * This method uses an * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index fb1c260305..0f54bef685 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -59,7 +59,7 @@ * Implemented by {@link ReactiveMongoTemplate}. Not often used but a useful option for extensibility and testability * (as it can be easily mocked, stubbed, or be the target of a JDK proxy). Command execution using * {@link ReactiveMongoOperations} is deferred until subscriber subscribes to the {@link Publisher}. - *

      + *
      * NOTE: Some operations cannot be executed within a MongoDB transaction. Please refer to the MongoDB * specific documentation to learn more about Multi * Document Transactions. @@ -121,7 +121,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { /** * Executes a {@link ReactiveDatabaseCallback} translating any exceptions as necessary. - *

      + *
      * Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param action callback object that specifies the MongoDB actions to perform on the passed in DB instance. Must not @@ -133,7 +133,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { /** * Executes the given {@link ReactiveCollectionCallback} on the entity collection of the specified class. - *

      + *
      * Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param entityClass class that determines the collection to use. Must not be {@literal null}. @@ -145,7 +145,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { /** * Executes the given {@link ReactiveCollectionCallback} on the collection of the given name. - *

      + *
      * Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param collectionName the name of the collection that specifies which {@link MongoCollection} instance will be @@ -159,7 +159,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { /** * Obtain a {@link ClientSession session} bound instance of {@link SessionScoped} binding the {@link ClientSession} * provided by the given {@link Supplier} to each and every command issued against MongoDB. - *

      + *
      * Note: It is up to the caller to manage the {@link ClientSession} lifecycle. Use * {@link ReactiveSessionScoped#execute(ReactiveSessionCallback, Consumer)} to provide a hook for processing the * {@link ClientSession} when done. @@ -178,7 +178,7 @@ default ReactiveSessionScoped withSession(Supplier sessionProvide /** * Obtain a {@link ClientSession session} bound instance of {@link SessionScoped} binding a new {@link ClientSession} * with given {@literal sessionOptions} to each and every command issued against MongoDB. - *

      + *
      * Note: It is up to the caller to manage the {@link ClientSession} lifecycle. Use * {@link ReactiveSessionScoped#execute(ReactiveSessionCallback, Consumer)} to provide a hook for processing the * {@link ClientSession} when done. @@ -192,7 +192,7 @@ default ReactiveSessionScoped withSession(Supplier sessionProvide /** * Obtain a {@link ClientSession session} bound instance of {@link ReactiveSessionScoped} binding the * {@link ClientSession} provided by the given {@link Publisher} to each and every command issued against MongoDB. - *

      + *
      * Note: It is up to the caller to manage the {@link ClientSession} lifecycle. Use * {@link ReactiveSessionScoped#execute(ReactiveSessionCallback, Consumer)} to provide a hook for processing the * {@link ClientSession} when done. @@ -205,7 +205,7 @@ default ReactiveSessionScoped withSession(Supplier sessionProvide /** * Obtain a {@link ClientSession} bound instance of {@link ReactiveMongoOperations}. - *

      + *
      * Note: It is up to the caller to manage the {@link ClientSession} lifecycle. * * @param session must not be {@literal null}. @@ -218,7 +218,7 @@ default ReactiveSessionScoped withSession(Supplier sessionProvide * Initiate a new {@link ClientSession} and obtain a {@link ClientSession session} bound instance of * {@link ReactiveSessionScoped}. Starts the transaction and adds the {@link ClientSession} to each and every command * issued against MongoDB. - *

      + *
      * Each {@link ReactiveSessionScoped#execute(ReactiveSessionCallback) execution} initiates a new managed transaction * that is {@link ClientSession#commitTransaction() committed} on success. Transactions are * {@link ClientSession#abortTransaction() rolled back} upon errors. @@ -233,7 +233,7 @@ default ReactiveSessionScoped withSession(Supplier sessionProvide * Obtain a {@link ClientSession session} bound instance of {@link ReactiveSessionScoped}, start the transaction and * bind the {@link ClientSession} provided by the given {@link Publisher} to each and every command issued against * MongoDB. - *

      + *
      * Each {@link ReactiveSessionScoped#execute(ReactiveSessionCallback) execution} initiates a new managed transaction * that is {@link ClientSession#commitTransaction() committed} on success. Transactions are * {@link ClientSession#abortTransaction() rolled back} upon errors. @@ -293,7 +293,7 @@ Mono> createCollection(Class entityClass, * created on first interaction with the server. Collections can be explicitly created via * {@link #createCollection(Class)}. Please make sure to check if the collection {@link #collectionExists(Class) * exists} first. - *

      + *
      * Translate any exceptions as necessary. * * @param collectionName name of the collection. @@ -303,7 +303,7 @@ Mono> createCollection(Class entityClass, /** * Check to see if a collection with a name indicated by the entity class exists. - *

      + *
      * Translate any exceptions as necessary. * * @param entityClass class that determines the name of the collection. Must not be {@literal null}. @@ -313,7 +313,7 @@ Mono> createCollection(Class entityClass, /** * Check to see if a collection with a given name exists. - *

      + *
      * Translate any exceptions as necessary. * * @param collectionName name of the collection. Must not be {@literal null}. @@ -323,7 +323,7 @@ Mono> createCollection(Class entityClass, /** * Drop the collection with the name indicated by the entity class. - *

      + *
      * Translate any exceptions as necessary. * * @param entityClass class that determines the collection to drop/delete. Must not be {@literal null}. @@ -332,7 +332,7 @@ Mono> createCollection(Class entityClass, /** * Drop the collection with the given name. - *

      + *
      * Translate any exceptions as necessary. * * @param collectionName name of the collection to drop/delete. @@ -341,10 +341,10 @@ Mono> createCollection(Class entityClass, /** * Query for a {@link Flux} of objects of type T from the collection used by the entity class. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way * to map objects since the test for class type is done in the client and not on the server. * @@ -355,10 +355,10 @@ Mono> createCollection(Class entityClass, /** * Query for a {@link Flux} of objects of type T from the specified collection. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way * to map objects since the test for class type is done in the client and not on the server. * @@ -371,10 +371,10 @@ Mono> createCollection(Class entityClass, /** * Map the results of an ad-hoc query on the collection for the entity class to a single instance of an object of the * specified type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -388,10 +388,10 @@ Mono> createCollection(Class entityClass, /** * Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified * type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -435,10 +435,10 @@ Mono> createCollection(Class entityClass, /** * Map the results of an ad-hoc query on the collection for the entity class to a {@link Flux} of the specified type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -451,10 +451,10 @@ Mono> createCollection(Class entityClass, /** * Map the results of an ad-hoc query on the specified collection to a {@link Flux} of the specified type. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -566,10 +566,10 @@ default Flux findDistinct(Query query, String field, String collection, C /** * Execute an aggregation operation. - *

      + *
      * The raw results will be mapped to the given entity class and are returned as stream. The name of the * inputCollection is derived from the {@link TypedAggregation#getInputType() aggregation input type}. - *

      + *
      * Aggregation streaming cannot be used with {@link AggregationOptions#isExplain() aggregation explain} nor with * {@link AggregationOptions#getCursorBatchSize()}. Enabling explanation mode or setting batch size cause * {@link IllegalArgumentException}. @@ -584,10 +584,10 @@ default Flux findDistinct(Query query, String field, String collection, C /** * Execute an aggregation operation. - *

      + *
      * The raw results will be mapped to the given {@code ouputType}. The name of the inputCollection is derived from the * {@code inputType}. - *

      + *
      * Aggregation streaming cannot be used with {@link AggregationOptions#isExplain() aggregation explain} nor with * {@link AggregationOptions#getCursorBatchSize()}. Enabling explanation mode or setting batch size cause * {@link IllegalArgumentException}. @@ -604,9 +604,9 @@ default Flux findDistinct(Query query, String field, String collection, C /** * Execute an aggregation operation. - *

      + *
      * The raw results will be mapped to the given entity class. - *

      + *
      * Aggregation streaming cannot be used with {@link AggregationOptions#isExplain() aggregation explain} nor with * {@link AggregationOptions#getCursorBatchSize()}. Enabling explanation mode or setting batch size cause * {@link IllegalArgumentException}. @@ -676,7 +676,7 @@ default Flux findDistinct(Query query, String field, String collection, C Flux> geoNear(NearQuery near, Class entityClass, String collectionName); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. * * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional @@ -691,7 +691,7 @@ default Flux findDistinct(Query query, String field, String collection, C Mono findAndModify(Query query, UpdateDefinition update, Class entityClass); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. * * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional @@ -707,7 +707,7 @@ default Flux findDistinct(Query query, String field, String collection, C Mono findAndModify(Query query, UpdateDefinition update, Class entityClass, String collectionName); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking * {@link FindAndModifyOptions} into account. * @@ -725,7 +725,7 @@ default Flux findDistinct(Query query, String field, String collection, C Mono findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class entityClass); /** - * Triggers findAndModify + * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking * {@link FindAndModifyOptions} into account. * @@ -746,7 +746,7 @@ Mono findAndModify(Query query, UpdateDefinition update, FindAndModifyOpt /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} * document.
      * Options are defaulted to {@link FindAndReplaceOptions#empty()}.
      @@ -764,7 +764,7 @@ default Mono findAndReplace(Query query, T replacement) { /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} * document.
      * Options are defaulted to {@link FindAndReplaceOptions#empty()}.
      @@ -783,7 +783,7 @@ default Mono findAndReplace(Query query, T replacement, String collection /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -803,7 +803,7 @@ default Mono findAndReplace(Query query, T replacement, FindAndReplaceOpt /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -825,7 +825,7 @@ default Mono findAndReplace(Query query, T replacement, FindAndReplaceOpt /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -849,7 +849,7 @@ default Mono findAndReplace(Query query, T replacement, FindAndReplaceOpt /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -876,7 +876,7 @@ default Mono findAndReplace(Query query, S replacement, FindAndReplace /** * Triggers - * findOneAndReplace + * findOneAndReplace * to replace a single document matching {@link Criteria} of given {@link Query} with the {@code replacement} document * taking {@link FindAndReplaceOptions} into account.
      * NOTE: The replacement entity must not hold an {@literal id}. @@ -902,9 +902,9 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * Map the results of an ad-hoc query on the collection for the entity type to a single instance of an object of the * specified type. The first document that matches the query is returned and also removed from the collection in the * database. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -918,10 +918,10 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions /** * Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified * type. The first document that matches the query is returned and also removed from the collection in the database. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -940,7 +940,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. - *

      + *
      * This method uses an * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees @@ -962,7 +962,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. - *

      + *
      * This method uses an * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees @@ -983,7 +983,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. - *

      + *
      * This method uses an * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees @@ -1001,7 +1001,7 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions /** * Estimate the number of documents, in the collection {@link #getCollectionName(Class) identified by the given type}, * based on collection statistics. - *

      + *
      * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside * transactions. * @@ -1017,7 +1017,7 @@ default Mono estimatedCount(Class entityClass) { /** * Estimate the number of documents in the given collection based on collection statistics. - *

      + *
      * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside * transactions. * @@ -1029,17 +1029,17 @@ default Mono estimatedCount(Class entityClass) { /** * Insert the object into the collection for the entity type of the object to save. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See * Spring's * Type Conversion" for more details. - *

      + *
      * Insert is used to initially store the object into the database. To update an existing object use the save method. - *

      + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1050,12 +1050,12 @@ default Mono estimatedCount(Class entityClass) { /** * Insert the object into the specified collection. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * Insert is used to initially store the object into the database. To update an existing object use the save method. - *

      + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1094,15 +1094,15 @@ default Mono estimatedCount(Class entityClass) { /** * Insert the object into the collection for the entity type of the object to save. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See * Spring's * Type Conversion" for more details. - *

      + *
      * Insert is used to initially store the object into the database. To update an existing object use the save method. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1140,16 +1140,16 @@ default Mono estimatedCount(Class entityClass) { /** * Save the object to the collection for the entity type of the object to save. This will perform an insert if the * object is not already present, that is an 'upsert'. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See * Spring's * Type Conversion" for more details. - *

      + *
      * The {@code objectToSave} must not be collection-like. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. @@ -1161,15 +1161,14 @@ default Mono estimatedCount(Class entityClass) { /** * Save the object to the specified collection. This will perform an insert if the object is not already present, that * is an 'upsert'. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your - * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See Spring's Type - * Conversion" for more details. + * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. + * See Spring's Type Conversion for more details. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @param collectionName name of the collection to store the object in. Must not be {@literal null}. @@ -1181,15 +1180,14 @@ default Mono estimatedCount(Class entityClass) { /** * Save the object to the collection for the entity type of the object to save. This will perform an insert if the * object is not already present, that is an 'upsert'. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your - * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See - * Spring's - * Type Conversion" for more details. + * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. + * See Spring's Type Conversion for more details. * * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @return the saved object. @@ -1199,17 +1197,16 @@ default Mono estimatedCount(Class entityClass) { /** * Save the object to the specified collection. This will perform an insert if the object is not already present, that * is an 'upsert'. - *

      + *
      * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your - * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See Spring's Type - * Conversion" for more details. + * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. + * See Spring's Type Conversion for more details. * - * @param objectToSave the object to store in the collection. Must not be {@literal null}. + * @param objectToSave the object to store in the collReactiveMongoOperationsection. Must not be {@literal null}. * @param collectionName name of the collection to store the object in. Must not be {@literal null}. * @return the saved object. */ @@ -1481,10 +1478,10 @@ default Mono estimatedCount(Class entityClass) { * type. The stream uses a {@link com.mongodb.CursorType#TailableAwait tailable} cursor that may be an infinite * stream. The stream will not be completed unless the {@link org.reactivestreams.Subscription} is * {@link Subscription#cancel() canceled}. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -1500,10 +1497,10 @@ default Mono estimatedCount(Class entityClass) { * type. The stream uses a {@link com.mongodb.CursorType#TailableAwait tailable} cursor that may be an infinite * stream. The stream will not be completed unless the {@link org.reactivestreams.Subscription} is * {@link Subscription#cancel() canceled}. - *

      + *
      * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless * configured otherwise, an instance of {@link MappingMongoConverter} will be used. - *

      + *
      * The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more * feature rich {@link Query}. * @@ -1520,10 +1517,10 @@ default Mono estimatedCount(Class entityClass) { * the configured default database via the reactive infrastructure. Use the optional provided {@link Aggregation} to * filter events. The stream will not be completed unless the {@link org.reactivestreams.Subscription} is * {@link Subscription#cancel() canceled}. - *

      + *
      * The {@link ChangeStreamEvent#getBody()} is mapped to the {@literal resultType} while the * {@link ChangeStreamEvent#getRaw()} contains the unmodified payload. - *

      + *
      * Use {@link ChangeStreamOptions} to set arguments like {@link ChangeStreamOptions#getResumeToken() the resumseToken} * for resuming change streams. * @@ -1544,10 +1541,10 @@ default Flux> changeStream(ChangeStreamOptions options, * the given collection via the reactive infrastructure. Use the optional provided {@link Aggregation} to filter * events. The stream will not be completed unless the {@link org.reactivestreams.Subscription} is * {@link Subscription#cancel() canceled}. - *

      + *
      * The {@link ChangeStreamEvent#getBody()} is mapped to the {@literal resultType} while the * {@link ChangeStreamEvent#getRaw()} contains the unmodified payload. - *

      + *
      * Use {@link ChangeStreamOptions} to set arguments like {@link ChangeStreamOptions#getResumeToken() the resumseToken} * for resuming change streams. * @@ -1569,10 +1566,10 @@ default Flux> changeStream(@Nullable String collectionN * Subscribe to a MongoDB Change Stream via the reactive * infrastructure. Use the optional provided {@link Aggregation} to filter events. The stream will not be completed * unless the {@link org.reactivestreams.Subscription} is {@link Subscription#cancel() canceled}. - *

      + *
      * The {@link ChangeStreamEvent#getBody()} is mapped to the {@literal resultType} while the * {@link ChangeStreamEvent#getRaw()} contains the unmodified payload. - *

      + *
      * Use {@link ChangeStreamOptions} to set arguments like {@link ChangeStreamOptions#getResumeToken() the resumseToken} * for resuming change streams. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 82a3d12260..a7d0113e8f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -362,7 +362,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws * Set the {@link ReactiveEntityCallbacks} instance to use when invoking * {@link org.springframework.data.mapping.callback.EntityCallback callbacks} like the * {@link ReactiveBeforeSaveCallback}. - *

      + *
      * Overrides potentially existing {@link ReactiveEntityCallbacks}. * * @param entityCallbacks must not be {@literal null}. @@ -2537,7 +2537,7 @@ private Document getMappedValidator(Validator validator, Class domainType) { /** * Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter. * The first document that matches the query is returned and also removed from the collection in the database. - *

      + *
      * The query document is specified as a standard Document and so is the fields specification. * * @param collectionName name of the collection to retrieve the objects from @@ -3390,7 +3390,7 @@ private static List toDocuments(Collection + *
      * The prepare steps for {@link MongoDatabase} and {@link MongoCollection} proxy the target and invoke the desired * target method matching the actual arguments plus a {@link ClientSession}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java index c9b15324fc..8ac447eeb5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionCallback.java @@ -32,7 +32,7 @@ public interface ReactiveSessionCallback { /** * Execute operations against a MongoDB instance via session bound {@link ReactiveMongoOperations}. The session is * inferred directly into the operation so that no further interaction is necessary. - *

      + *
      * Please note that only Spring Data-specific abstractions like {@link ReactiveMongoOperations#find(Query, Class)} and * others are enhanced with the {@link com.mongodb.session.ClientSession}. When obtaining plain MongoDB gateway * objects like {@link com.mongodb.reactivestreams.client.MongoCollection} or diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java index 17c17edd24..2519a8bb1a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveSessionScoped.java @@ -33,7 +33,7 @@ public interface ReactiveSessionScoped { /** * Executes the given {@link ReactiveSessionCallback} within the {@link com.mongodb.session.ClientSession}. - *

      + *
      * It is up to the caller to make sure the {@link com.mongodb.session.ClientSession} is {@link ClientSession#close() * closed} when done. * @@ -47,7 +47,7 @@ default Flux execute(ReactiveSessionCallback action) { /** * Executes the given {@link ReactiveSessionCallback} within the {@link com.mongodb.session.ClientSession}. - *

      + *
      * It is up to the caller to make sure the {@link com.mongodb.session.ClientSession} is {@link ClientSession#close() * closed} when done. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java index 24ad1c5ffc..36f8113021 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java @@ -23,7 +23,7 @@ /** - * Script operations on {@link com.mongodb.DB} level. Allows interaction with server side JavaScript functions. + * Script operations on {@link com.mongodb.client.MongoDatabase} level. Allows interaction with server side JavaScript functions. * * @author Christoph Strobl * @author Oliver Gierke @@ -72,10 +72,10 @@ public interface ScriptOperations { Object call(String scriptName, Object... args); /** - * Checks {@link DB} for existence of {@link ServerSideJavaScript} with given name. + * Checks {@link com.mongodb.client.MongoDatabase} for existence of {@literal ServerSideJavaScript} with given name. * * @param scriptName must not be {@literal null} or empty. - * @return false if no {@link ServerSideJavaScript} with given name exists. + * @return false if no {@literal ServerSideJavaScript} with given name exists. */ boolean exists(String scriptName); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java index c12d4b1005..93d0c71378 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionCallback.java @@ -31,7 +31,7 @@ public interface SessionCallback { /** * Execute operations against a MongoDB instance via session bound {@link MongoOperations}. The session is inferred * directly into the operation so that no further interaction is necessary. - *

      + *
      * Please note that only Spring Data-specific abstractions like {@link MongoOperations#find(Query, Class)} and others * are enhanced with the {@link com.mongodb.session.ClientSession}. When obtaining plain MongoDB gateway objects like * {@link com.mongodb.client.MongoCollection} or {@link com.mongodb.client.MongoDatabase} via eg. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java index ead52ee15e..5bba65144a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SessionScoped.java @@ -23,7 +23,7 @@ /** * Gateway interface to execute {@link ClientSession} bound operations against MongoDB via a {@link SessionCallback}. - *

      + *
      * The very same bound {@link ClientSession} is used for all invocations of {@code execute} on the instance. * * @author Christoph Strobl @@ -34,7 +34,7 @@ public interface SessionScoped { /** * Executes the given {@link SessionCallback} within the {@link com.mongodb.session.ClientSession}. - *

      + *
      * It is up to the caller to make sure the {@link com.mongodb.session.ClientSession} is {@link ClientSession#close() * closed} when done. * @@ -49,7 +49,7 @@ default T execute(SessionCallback action) { /** * Executes the given {@link SessionCallback} within the {@link com.mongodb.session.ClientSession}. - *

      + *
      * It is up to the caller to make sure the {@link com.mongodb.session.ClientSession} is {@link ClientSession#close() * closed} when done. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index 614489692c..e4894fbef0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -227,7 +227,7 @@ public static String previousOperation() { /** * Obtain an {@link AddFieldsOperationBuilder builder} instance to create a new {@link AddFieldsOperation}. - *

      + *
      * Starting in version 4.2, MongoDB adds a new aggregation pipeline stage {@link AggregationUpdate#set $set} that is * an alias for {@code $addFields}. * @@ -726,7 +726,7 @@ public AggregationPipeline getPipeline() { /** * Converts this {@link Aggregation} specification to a {@link Document}. - *

      + *
      * MongoDB requires as of 3.6 cursor-based aggregation. Use {@link #toPipeline(AggregationOperationContext)} to render * an aggregation pipeline. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java index 14fa8c48d1..e406f57874 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationSpELExpression.java @@ -24,15 +24,15 @@ * expression.
      *
      * Samples:
      - * *

      + * 
        * // { $and: [ { $gt: [ "$qty", 100 ] }, { $lt: [ "$qty", 250 ] } ] }
        * expressionOf("qty > 100 && qty < 250);
        *
        * // { $cond : { if : { $gte : [ "$a", 42 ]}, then : "answer", else : "no-answer" } }
        * expressionOf("cond(a >= 42, 'answer', 'no-answer')");
      - * 
      * + *
      * * @author Christoph Strobl * @author Mark Paluch diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index e69531e036..3cbb5f8735 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -71,8 +71,7 @@ * * @author Christoph Strobl * @author Mark Paluch - * @see MongoDB + * @see MongoDB * Reference Documentation * @since 3.0 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java index 9c9132e679..0fbfcac411 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java @@ -825,7 +825,7 @@ public ATan atan() { * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value divided by * the given numeric value in the argument. * - * @param the numeric value + * @param value the numeric value * @return new instance of {@link ATan2}. * @since 3.3 */ @@ -839,7 +839,7 @@ public ATan2 atan2(Number value) { * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value divided by * the given field reference in the argument. * - * @param the numeric value + * @param fieldReference the numeric value * @return new instance of {@link ATan2}. * @since 3.3 */ @@ -853,7 +853,7 @@ public ATan2 atan2(String fieldReference) { * Creates new {@link AggregationExpression} that calculates the inverse tangent of the the numeric value divided by * the given {@link AggregationExpression} in the argument. * - * @param the numeric value + * @param expression the expression evaluating to a numeric value * @return new instance of {@link ATan2}. * @since 3.3 */ @@ -2169,7 +2169,7 @@ private Sin(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in * {@link AngularUnit#RADIANS radians}. - *

      + *
      * Use {@code sinhOf("angle", DEGREES)} as shortcut for * *

      @@ -2282,7 +2282,7 @@ public static Sinh sinhOf(String fieldReference) {
       		/**
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
       		 * the given {@link AngularUnit unit}.
      -		 * 

      + *
      * Use {@code sinhOf("angle", DEGREES)} as shortcut for * *

      @@ -2302,7 +2302,7 @@ public static Sinh sinhOf(String fieldReference, AngularUnit unit) {
       		/**
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
       		 * {@link AngularUnit#RADIANS}.
      -		 * 

      + *
      * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. * @@ -2386,7 +2386,7 @@ public static ASin asinOf(String fieldReference) { /** * Creates a new {@link AggregationExpression} that calculates the inverse sine of a value. - *

      + *
      * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ASin}. @@ -2436,7 +2436,7 @@ public static ASinh asinhOf(String fieldReference) { /** * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic sine of a value. - *

      + *
      * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ASinh}. @@ -2478,7 +2478,7 @@ private Cos(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the cosine of a value that is measured in * {@link AngularUnit#RADIANS radians}. - *

      + *
      * Use {@code cosOf("angle", DEGREES)} as shortcut for * *

      @@ -2589,7 +2589,7 @@ public static Cosh coshOf(String fieldReference) {
       		/**
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in
       		 * the given {@link AngularUnit unit}.
      -		 * 

      + *
      * Use {@code coshOf("angle", DEGREES)} as shortcut for * *

      @@ -2607,7 +2607,7 @@ public static Cosh coshOf(String fieldReference, AngularUnit unit) {
       		/**
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic cosine of a value that is measured in
       		 * {@link AngularUnit#RADIANS}.
      -		 * 

      + *
      * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. * @@ -2680,7 +2680,7 @@ private Tan(Object value) { /** * Creates a new {@link AggregationExpression} that calculates the tangent of a value that is measured in * {@link AngularUnit#RADIANS radians}. - *

      + *
      * Use {@code tanOf("angle", DEGREES)} as shortcut for * *

      @@ -2859,7 +2859,7 @@ public static ATan2 valueOf(AggregationExpression expression) {
       		 * Creates a new {@link AggregationExpression} that calculates the inverse tangent of of y / x, where y and x are
       		 * the first and second values passed to the expression respectively.
       		 *
      -		 * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
      +		 * @param fieldReference anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
       		 *          numeric value.
       		 * @return new instance of {@link ATan2}.
       		 */
      @@ -2873,7 +2873,7 @@ public ATan2 atan2of(String fieldReference) {
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in
       		 * {@link AngularUnit#RADIANS}.
       		 *
      -		 * @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
      +		 * @param expression anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
       		 *          numeric value.
       		 * @return new instance of {@link ATan2}.
       		 */
      @@ -2927,7 +2927,7 @@ public static Tanh tanhOf(String fieldReference) {
       		/**
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in
       		 * the given {@link AngularUnit unit}.
      -		 * 

      + *
      * Use {@code tanhOf("angle", DEGREES)} as shortcut for * *

      @@ -2945,7 +2945,7 @@ public static Tanh tanhOf(String fieldReference, AngularUnit unit) {
       		/**
       		 * Creates a new {@link AggregationExpression} that calculates the hyperbolic tangent of a value that is measured in
       		 * {@link AngularUnit#RADIANS}.
      -		 * 

      + *
      * Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. * {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}. * @@ -3029,7 +3029,7 @@ public static ATanh atanhOf(String fieldReference) { /** * Creates a new {@link AggregationExpression} that calculates the inverse hyperbolic tangent of a value. - *

      + *
      * * @param expression the {@link AggregationExpression expression} that resolves to a numeric value. * @return new instance of {@link ATanh}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java index 235c16befe..f5755346bb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketAutoOperation.java @@ -28,8 +28,7 @@ * We recommend to use the static factory method {@link Aggregation#bucketAuto(String, int)} instead of creating * instances of this class directly. * - * @see https://docs.mongodb.org/manual/reference/aggregation/bucketAuto/ + * @see https://docs.mongodb.org/manual/reference/aggregation/bucketAuto/ * @see BucketOperationSupport * @author Mark Paluch * @author Christoph Strobl @@ -248,8 +247,7 @@ public interface Granularity { /** * Supported MongoDB granularities. * - * @see https://docs.mongodb.com/manual/reference/operator/aggregation/bucketAuto/#granularity * @author Mark Paluch */ public enum Granularities implements Granularity { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java index 173fa4ece5..937ec029cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/BucketOperation.java @@ -31,8 +31,7 @@ * We recommend to use the static factory method {@link Aggregation#bucket(String)} instead of creating instances of * this class directly. * - * @see https://docs.mongodb.org/manual/reference/aggregation/bucket/ + * @see https://docs.mongodb.org/manual/reference/aggregation/bucket/ * @see BucketOperationSupport * @author Mark Paluch * @since 1.10 diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java index 637ebd8d8f..3555ada8a7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ConvertOperators.java @@ -328,9 +328,9 @@ public Convert to(String stringTypeIdentifier) { *

      1
      *
      double
      *
      2
      - *
      string + *
      string
      *
      7
      - *
      objectId + *
      objectId
      *
      8
      *
      bool
      *
      9
      diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java index e2b65aa7ff..95e63ac8f7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/CountOperation.java @@ -24,8 +24,7 @@ * We recommend to use the static factory method {@link Aggregation#count()} instead of creating instances of this class * directly. * - * @see https://docs.mongodb.com/manual/reference/operator/aggregation/count/ + * @see https://docs.mongodb.com/manual/reference/operator/aggregation/count/ * @author Mark Paluch * @since 1.10 */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java index 029b994f2e..d1e45a8b93 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DateOperators.java @@ -92,7 +92,7 @@ public static DateOperatorFactory zonedDateOf(AggregationExpression expression, /** * Take the given value as date. - *

      + *
      * This can be one of: *